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/07/26 16:15:35 UTC

[camel] branch master updated (efd7aaa -> 0a88d13)

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

gnodet pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from efd7aaa  Regen
     add 6512ee0  [CAMEL-12689] EndpointRegistry, TransformerRegistry and ValidatorRegistry use wrong generics
     add 8d7eee4  [CAMEL-12688] Add specific implementation of getShortName() to avoid reflection during route setup
     add ff41e9f  [CAMEL-12688] Add protected methods to allow subclass to provide specific implementations
     new 2a8432d  [CAMEL-12688] Possibility to use a simple LRUCache
     new 9fc335f  [CAMEL-12688] Avoid lamba
     new 0e9830d  [CAMEL-12688] Improve Scanner performances
     new 7af6206  [CAMEL-12688] Improve introspection performances
     new 0a88d13  [CAMEL-12688] Generate a fallback converter containing all core converters for performances

The 5 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/CamelContext.java   |   7 +-
 .../apache/camel/builder/ExpressionBuilder.java    |  11 +-
 .../apache/camel/component/bean/BeanComponent.java |   7 +-
 .../camel/component/dataset/FileDataSet.java       |   8 +-
 .../camel/component/file/GenericFileProducer.java  |   4 +-
 .../java/org/apache/camel/impl/ConsumerCache.java  |   2 +-
 .../org/apache/camel/impl/DefaultCamelContext.java | 237 ++++++++++++----
 .../apache/camel/impl/DefaultEndpointRegistry.java | 105 ++++---
 .../impl/DefaultEndpointUtilizationStatistics.java |   7 +-
 .../apache/camel/impl/DefaultFactoryFinder.java    |  29 +-
 .../camel/impl/DefaultTransformerRegistry.java     | 105 +++----
 .../camel/impl/DefaultValidatorRegistry.java       | 106 ++++---
 .../java/org/apache/camel/impl/EndpointKey.java    |  11 +-
 .../org/apache/camel/impl/FileStateRepository.java |  15 +-
 .../java/org/apache/camel/impl/ProducerCache.java  |   2 +-
 .../impl/converter/BaseTypeConverterRegistry.java  |   3 +-
 .../language/simple/SimpleExpressionParser.java    |   6 +-
 .../camel/language/simple/SimpleLanguage.java      |  16 +-
 .../language/simple/SimplePredicateParser.java     |   5 +-
 .../simple/ast/SimpleFunctionExpression.java       |   6 +-
 .../language/simple/ast/SimpleFunctionStart.java   |   6 +-
 .../camel/management/MBeanInfoAssembler.java       |   5 +-
 .../java/org/apache/camel/model/AOPDefinition.java |   5 +
 .../apache/camel/model/AggregateDefinition.java    |   5 +
 .../org/apache/camel/model/BeanDefinition.java     |   5 +
 .../org/apache/camel/model/CatchDefinition.java    |   5 +
 .../org/apache/camel/model/ChoiceDefinition.java   |   5 +
 .../apache/camel/model/ClaimCheckDefinition.java   |   5 +
 .../apache/camel/model/ConvertBodyDefinition.java  |   5 +
 .../org/apache/camel/model/DelayDefinition.java    |   5 +
 .../camel/model/DynamicRouterDefinition.java       |   5 +
 .../org/apache/camel/model/EnrichDefinition.java   |   5 +
 .../org/apache/camel/model/FilterDefinition.java   |   5 +
 .../org/apache/camel/model/FinallyDefinition.java  |   5 +
 .../org/apache/camel/model/FromDefinition.java     |   6 +
 .../org/apache/camel/model/HystrixDefinition.java  |   5 +
 .../camel/model/IdempotentConsumerDefinition.java  |   5 +
 .../org/apache/camel/model/InOnlyDefinition.java   |   5 +
 .../org/apache/camel/model/InOutDefinition.java    |   5 +
 .../apache/camel/model/InputTypeDefinition.java    |   5 +
 .../apache/camel/model/InterceptDefinition.java    |   5 +
 .../camel/model/InterceptFromDefinition.java       |   5 +
 .../model/InterceptSendToEndpointDefinition.java   |   5 +
 .../apache/camel/model/LoadBalanceDefinition.java  |   5 +
 .../java/org/apache/camel/model/LogDefinition.java |   5 +
 .../org/apache/camel/model/LoopDefinition.java     |   5 +
 .../org/apache/camel/model/MarshalDefinition.java  |   5 +
 .../apache/camel/model/MulticastDefinition.java    |   5 +
 .../apache/camel/model/NoOutputExpressionNode.java |   2 +-
 .../apache/camel/model/OnCompletionDefinition.java |   5 +
 .../apache/camel/model/OnExceptionDefinition.java  |   5 +
 .../apache/camel/model/OnFallbackDefinition.java   |   5 +
 .../camel/model/OptionalIdentifiedDefinition.java  |  22 --
 .../apache/camel/model/OtherwiseDefinition.java    |   5 +
 .../org/apache/camel/model/OutputDefinition.java   |   5 +
 .../apache/camel/model/OutputTypeDefinition.java   |   5 +
 .../org/apache/camel/model/PipelineDefinition.java |   5 +
 .../apache/camel/model/PollEnrichDefinition.java   |   5 +
 .../org/apache/camel/model/ProcessDefinition.java  |   5 +
 .../camel/model/RecipientListDefinition.java       |   5 +
 .../apache/camel/model/RemoveHeaderDefinition.java |   5 +
 .../camel/model/RemoveHeadersDefinition.java       |   5 +
 .../camel/model/RemovePropertiesDefinition.java    |   5 +
 .../camel/model/RemovePropertyDefinition.java      |   5 +
 .../apache/camel/model/ResequenceDefinition.java   |   5 +
 .../org/apache/camel/model/RollbackDefinition.java |   5 +
 .../org/apache/camel/model/RouteDefinition.java    |   5 +
 .../org/apache/camel/model/RoutesDefinition.java   |   5 +
 .../apache/camel/model/RoutingSlipDefinition.java  |   5 +
 .../org/apache/camel/model/ScriptDefinition.java   |   5 +
 .../org/apache/camel/model/SetBodyDefinition.java  |   5 +
 .../camel/model/SetExchangePatternDefinition.java  |   5 +
 .../apache/camel/model/SetFaultBodyDefinition.java |   5 +
 .../apache/camel/model/SetHeaderDefinition.java    |   5 +
 .../apache/camel/model/SetOutHeaderDefinition.java |   5 +
 .../apache/camel/model/SetPropertyDefinition.java  |   5 +
 .../org/apache/camel/model/SortDefinition.java     |   5 +
 .../org/apache/camel/model/SplitDefinition.java    |   5 +
 .../org/apache/camel/model/StopDefinition.java     |   5 +
 .../camel/model/ThreadPoolProfileDefinition.java   |   5 +
 .../org/apache/camel/model/ThreadsDefinition.java  |   5 +
 .../org/apache/camel/model/ThrottleDefinition.java |   5 +
 .../camel/model/ThrowExceptionDefinition.java      |   5 +
 .../java/org/apache/camel/model/ToDefinition.java  |   5 +
 .../apache/camel/model/ToDynamicDefinition.java    |   5 +
 .../apache/camel/model/TransactedDefinition.java   |   5 +
 .../apache/camel/model/TransformDefinition.java    |   5 +
 .../java/org/apache/camel/model/TryDefinition.java |   5 +
 .../apache/camel/model/UnmarshalDefinition.java    |   5 +
 .../org/apache/camel/model/ValidateDefinition.java |   5 +
 .../org/apache/camel/model/WhenDefinition.java     |   5 +
 .../model/WhenSkipSendToEndpointDefinition.java    |   4 +
 .../org/apache/camel/model/WireTapDefinition.java  |   5 +
 .../camel/model/cloud/ServiceCallDefinition.java   |   5 +
 .../camel/model/rest/RestBindingDefinition.java    |   5 +
 .../apache/camel/model/rest/RestDefinition.java    |   5 +
 .../apache/camel/model/rest/RestsDefinition.java   |   5 +
 .../apache/camel/model/rest/VerbDefinition.java    |   5 +
 .../java/org/apache/camel/processor/Splitter.java  |  15 +-
 .../idempotent/FileIdempotentRepository.java       |  42 +--
 .../camel/support/TokenPairExpressionIterator.java |   4 +-
 .../support/TokenXMLPairExpressionIterator.java    |   4 +-
 .../{ValueHolder.java => CompoundIterator.java}    |  64 ++---
 .../java/org/apache/camel/util/GroupIterator.java  |  13 +-
 .../org/apache/camel/util/GroupTokenIterator.java  |  14 +-
 .../main/java/org/apache/camel/util/IOHelper.java  |  23 ++
 .../apache/camel/util/IntrospectionSupport.java    |  26 +-
 .../org/apache/camel/util/LRUCacheFactory.java     |  92 ++++++-
 .../java/org/apache/camel/util/ObjectHelper.java   |  59 ++--
 .../main/java/org/apache/camel/util/Scanner.java   | 303 +++++++++++++++++++++
 .../java/org/apache/camel/util/SkipIterator.java   |  14 +-
 .../apache/camel/util/GroupTokenIteratorTest.java  |  11 +-
 .../stored/CallableStatementWrapperFactory.java    |   6 +-
 .../apache/camel/tools/apt/ConverterProcessor.java | 198 ++++++++++++++
 .../services/javax.annotation.processing.Processor |   1 +
 115 files changed, 1486 insertions(+), 500 deletions(-)
 copy camel-core/src/main/java/org/apache/camel/util/{ValueHolder.java => CompoundIterator.java} (50%)
 create mode 100644 camel-core/src/main/java/org/apache/camel/util/Scanner.java
 create mode 100644 tooling/apt/src/main/java/org/apache/camel/tools/apt/ConverterProcessor.java


[camel] 01/05: [CAMEL-12688] Possibility to use a simple LRUCache

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

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 2a8432dd477ca4d6e58ed8c4948e5e942aa0c8fd
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Jun 22 23:02:11 2018 +0200

    [CAMEL-12688] Possibility to use a simple LRUCache
---
 .../apache/camel/component/bean/BeanComponent.java |   7 +-
 .../camel/component/file/GenericFileProducer.java  |   4 +-
 .../java/org/apache/camel/impl/ConsumerCache.java  |   2 +-
 .../org/apache/camel/impl/DefaultCamelContext.java |   7 --
 .../apache/camel/impl/DefaultEndpointRegistry.java | 105 ++++++++++----------
 .../impl/DefaultEndpointUtilizationStatistics.java |   7 +-
 .../camel/impl/DefaultTransformerRegistry.java     | 105 ++++++++++----------
 .../camel/impl/DefaultValidatorRegistry.java       | 106 ++++++++++-----------
 .../java/org/apache/camel/impl/ProducerCache.java  |   2 +-
 .../impl/converter/BaseTypeConverterRegistry.java  |   3 +-
 .../language/simple/SimpleExpressionParser.java    |   6 +-
 .../camel/language/simple/SimpleLanguage.java      |  16 ++--
 .../language/simple/SimplePredicateParser.java     |   5 +-
 .../simple/ast/SimpleFunctionExpression.java       |   6 +-
 .../language/simple/ast/SimpleFunctionStart.java   |   6 +-
 .../camel/management/MBeanInfoAssembler.java       |   5 +-
 .../org/apache/camel/util/CompoundIterator.java    |  64 +++++++++++++
 .../apache/camel/util/IntrospectionSupport.java    |   5 +-
 .../org/apache/camel/util/LRUCacheFactory.java     |  92 ++++++++++++++++--
 .../stored/CallableStatementWrapperFactory.java    |   6 +-
 20 files changed, 347 insertions(+), 212 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/BeanComponent.java b/camel-core/src/main/java/org/apache/camel/component/bean/BeanComponent.java
index bfffc4c..ba7cbaf 100644
--- a/camel-core/src/main/java/org/apache/camel/component/bean/BeanComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/component/bean/BeanComponent.java
@@ -21,8 +21,8 @@ import java.util.Map;
 import org.apache.camel.Endpoint;
 import org.apache.camel.impl.UriEndpointComponent;
 import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.LRUCache;
 import org.apache.camel.util.LRUCacheFactory;
-import org.apache.camel.util.LRUSoftCache;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,7 +35,7 @@ public class BeanComponent extends UriEndpointComponent {
     // use an internal soft cache for BeanInfo as they are costly to introspect
     // for example the bean language using OGNL expression runs much faster reusing the BeanInfo from this cache
     @SuppressWarnings("unchecked")
-    private final LRUSoftCache<BeanInfoCacheKey, BeanInfo> cache = LRUCacheFactory.newLRUSoftCache(1000);
+    private final Map<BeanInfoCacheKey, BeanInfo> cache = LRUCacheFactory.newLRUSoftCache(1000);
 
     public BeanComponent() {
         super(BeanEndpoint.class);
@@ -68,7 +68,8 @@ public class BeanComponent extends UriEndpointComponent {
 
     @Override
     protected void doShutdown() throws Exception {
-        if (LOG.isDebugEnabled()) {
+        if (LOG.isDebugEnabled() && cache instanceof LRUCache) {
+            LRUCache cache = (LRUCache) this.cache;
             LOG.debug("Clearing BeanInfo cache[size={}, hits={}, misses={}, evicted={}]", new Object[]{cache.size(), cache.getHits(), cache.getMisses(), cache.getEvicted()});
         }
         cache.clear();
diff --git a/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java b/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
index 2dec738..1fa9a25 100644
--- a/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
+++ b/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.file;
 
 import java.io.File;
+import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -25,7 +26,6 @@ import org.apache.camel.Expression;
 import org.apache.camel.impl.DefaultExchange;
 import org.apache.camel.impl.DefaultProducer;
 import org.apache.camel.util.FileUtil;
-import org.apache.camel.util.LRUCache;
 import org.apache.camel.util.LRUCacheFactory;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ServiceHelper;
@@ -41,7 +41,7 @@ public class GenericFileProducer<T> extends DefaultProducer {
     protected final GenericFileEndpoint<T> endpoint;
     protected GenericFileOperations<T> operations;
     // assume writing to 100 different files concurrently at most for the same file producer
-    private final LRUCache<String, Lock> locks = LRUCacheFactory.newLRUCache(100);
+    private final Map<String, Lock> locks = LRUCacheFactory.newLRUCache(100);
 
     protected GenericFileProducer(GenericFileEndpoint<T> endpoint, GenericFileOperations<T> operations) {
         super(endpoint);
diff --git a/camel-core/src/main/java/org/apache/camel/impl/ConsumerCache.java b/camel-core/src/main/java/org/apache/camel/impl/ConsumerCache.java
index a523a09..6492a0b 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/ConsumerCache.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/ConsumerCache.java
@@ -102,7 +102,7 @@ public class ConsumerCache extends ServiceSupport {
      * @return the cache
      */
     @SuppressWarnings("unchecked")
-    protected static LRUCache<String, PollingConsumer> createLRUCache(int cacheSize) {
+    protected static Map<String, PollingConsumer> createLRUCache(int cacheSize) {
         // Use a regular cache as we want to ensure that the lifecycle of the consumers
         // being cache is properly handled, such as they are stopped when being evicted
         // or when this cache is stopped. This is needed as some consumers requires to
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 873584e..d081cae 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -329,13 +329,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
      * Use one of the other constructors to force use an explicit registry / JNDI.
      */
     public DefaultCamelContext() {
-        boolean warmUp = "true".equalsIgnoreCase(System.getProperty("CamelWarmUpLRUCacheFactory", "true"));
-        if (warmUp) {
-            // warm-up LRUCache which happens in a background test, which can speedup starting Camel
-            // as the warm-up can run concurrently with starting up Camel and the runtime container Camel may be running inside
-            LRUCacheFactory.warmUp();
-        }
-
         this.executorServiceManager = createExecutorServiceManager();
 
         // create a provisional (temporary) endpoint registry at first since end users may access endpoints before CamelContext is started
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointRegistry.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointRegistry.java
index 7a230b4..bbe9c3a 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointRegistry.java
@@ -16,32 +16,37 @@
  */
 package org.apache.camel.impl;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashSet;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.spi.EndpointRegistry;
 import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.CompoundIterator;
 import org.apache.camel.util.LRUCache;
+import org.apache.camel.util.LRUCacheFactory;
 import org.apache.camel.util.ServiceHelper;
 
 /**
  * Default implementation of {@link org.apache.camel.spi.EndpointRegistry}
  */
-public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> implements EndpointRegistry<EndpointKey> {
+public class DefaultEndpointRegistry extends AbstractMap<EndpointKey, Endpoint> implements EndpointRegistry<EndpointKey> {
     private static final long serialVersionUID = 1L;
-    private ConcurrentMap<EndpointKey, Endpoint> staticMap;
+    private Map<EndpointKey, Endpoint> dynamicMap;
+    private Map<EndpointKey, Endpoint> staticMap;
     private final CamelContext context;
+    private int maxCacheSize;
 
     public DefaultEndpointRegistry(CamelContext context) {
-        // do not stop on eviction, as the endpoint may still be in use
-        super(CamelContextHelper.getMaximumEndpointCacheSize(context), CamelContextHelper.getMaximumEndpointCacheSize(context), false);
+        this.maxCacheSize = CamelContextHelper.getMaximumEndpointCacheSize(context);
+        // do not stop on eviction, as the validator may still be in use
+        this.dynamicMap = LRUCacheFactory.newLRUCache(maxCacheSize, maxCacheSize, false);
         // static map to hold endpoints we do not want to be evicted
         this.staticMap = new ConcurrentHashMap<>();
         this.context = context;
@@ -54,7 +59,9 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
 
     @Override
     public void start() throws Exception {
-        resetStatistics();
+        if (dynamicMap instanceof LRUCache) {
+            ((LRUCache) dynamicMap).resetStatistics();
+        }
     }
 
     @Override
@@ -62,9 +69,7 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
         // try static map first
         Endpoint answer = staticMap.get(o);
         if (answer == null) {
-            answer = super.get(o);
-        } else {
-            hits.increment();
+            answer = dynamicMap.get(o);
         }
         return answer;
     }
@@ -79,10 +84,10 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
             return answer;
         }
 
-        answer = super.remove(key);
+        answer = dynamicMap.remove(key);
         if (answer != null) {
             // replace existing
-            super.put(key, endpoint);
+            dynamicMap.put(key, endpoint);
             return answer;
         }
 
@@ -90,33 +95,25 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
         if (context.isSetupRoutes() || context.isStartingRoutes()) {
             answer = staticMap.put(key, endpoint);
         } else {
-            answer = super.put(key, endpoint);
+            answer = dynamicMap.put(key, endpoint);
         }
 
         return answer;
     }
 
     @Override
-    public void putAll(Map<? extends EndpointKey, ? extends Endpoint> map) {
-        // need to use put instead of putAll to ensure the entries gets added to either static or dynamic map
-        for (Map.Entry<? extends EndpointKey, ? extends Endpoint> entry : map.entrySet()) {
-            put(entry.getKey(), entry.getValue());
-        }
-    }
-
-    @Override
     public boolean containsKey(Object o) {
-        return staticMap.containsKey(o) || super.containsKey(o);
+        return staticMap.containsKey(o) || dynamicMap.containsKey(o);
     }
 
     @Override
     public boolean containsValue(Object o) {
-        return staticMap.containsValue(o) || super.containsValue(o);
+        return staticMap.containsValue(o) || dynamicMap.containsValue(o);
     }
 
     @Override
     public int size() {
-        return staticMap.size() + super.size();
+        return staticMap.size() + dynamicMap.size();
     }
 
     public int staticSize() {
@@ -125,19 +122,19 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
 
     @Override
     public int dynamicSize() {
-        return super.size();
+        return dynamicMap.size();
     }
 
     @Override
     public boolean isEmpty() {
-        return staticMap.isEmpty() && super.isEmpty();
+        return staticMap.isEmpty() && dynamicMap.isEmpty();
     }
 
     @Override
     public Endpoint remove(Object o) {
         Endpoint answer = staticMap.remove(o);
         if (answer == null) {
-            answer = super.remove(o);
+            answer = dynamicMap.remove(o);
         }
         return answer;
     }
@@ -145,36 +142,29 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
     @Override
     public void clear() {
         staticMap.clear();
-        super.clear();
-    }
-
-    @Override
-    public Set<EndpointKey> keySet() {
-        Set<EndpointKey> answer = new LinkedHashSet<>();
-        answer.addAll(staticMap.keySet());
-        answer.addAll(super.keySet());
-        return answer;
-    }
-
-    @Override
-    public Collection<Endpoint> values() {
-        Collection<Endpoint> answer = new ArrayList<>();
-        answer.addAll(staticMap.values());
-        answer.addAll(super.values());
-        return answer;
+        dynamicMap.clear();
     }
 
     @Override
     public Set<Entry<EndpointKey, Endpoint>> entrySet() {
-        Set<Entry<EndpointKey, Endpoint>> answer = new LinkedHashSet<>();
-        answer.addAll(staticMap.entrySet());
-        answer.addAll(super.entrySet());
-        return answer;
+        return new AbstractSet<Entry<EndpointKey, Endpoint>>() {
+            @Override
+            public Iterator<Entry<EndpointKey, Endpoint>> iterator() {
+                return new CompoundIterator<>(Arrays.asList(
+                        staticMap.entrySet().iterator(), dynamicMap.entrySet().iterator()
+                ));
+            }
+
+            @Override
+            public int size() {
+                return staticMap.size() + dynamicMap.size();
+            }
+        };
     }
 
     @Override
     public int getMaximumCacheSize() {
-        return super.getMaxCacheSize();
+        return maxCacheSize;
     }
 
     /**
@@ -183,7 +173,14 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
     @Override
     public void purge() {
         // only purge the dynamic part
-        super.clear();
+        dynamicMap.clear();
+    }
+
+    @Override
+    public void cleanUp() {
+        if (dynamicMap instanceof LRUCache) {
+            ((LRUCache) dynamicMap).cleanUp();
+        }
     }
 
     @Override
@@ -193,7 +190,7 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
 
     @Override
     public boolean isDynamic(String key) {
-        return super.containsKey(new EndpointKey(key));
+        return dynamicMap.containsKey(new EndpointKey(key));
     }
 
     @Override
@@ -205,6 +202,6 @@ public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> imp
 
     @Override
     public String toString() {
-        return "EndpointRegistry for " + context.getName() + ", capacity: " + getMaxCacheSize();
+        return "EndpointRegistry for " + context.getName() + ", capacity: " + maxCacheSize;
     }
 }
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointUtilizationStatistics.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointUtilizationStatistics.java
index f849728..3c93523 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointUtilizationStatistics.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultEndpointUtilizationStatistics.java
@@ -20,21 +20,22 @@ import java.util.Collections;
 import java.util.Map;
 
 import org.apache.camel.spi.EndpointUtilizationStatistics;
-import org.apache.camel.util.LRUCache;
 import org.apache.camel.util.LRUCacheFactory;
 
 public class DefaultEndpointUtilizationStatistics implements EndpointUtilizationStatistics {
 
-    private final LRUCache<String, Long> map;
+    private final int maxCapacity;
+    private final Map<String, Long> map;
 
     @SuppressWarnings("unchecked")
     public DefaultEndpointUtilizationStatistics(int maxCapacity) {
         this.map = LRUCacheFactory.newLRUCache(16, maxCapacity, false);
+        this.maxCapacity = maxCapacity;
     }
 
     @Override
     public int maxCapacity() {
-        return map.getMaxCacheSize();
+        return maxCapacity;
     }
 
     @Override
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultTransformerRegistry.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultTransformerRegistry.java
index feeb5f0..a64583d 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultTransformerRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultTransformerRegistry.java
@@ -16,8 +16,12 @@
  */
 package org.apache.camel.impl;
 
+import java.util.AbstractMap;
+import java.util.AbstractSet;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -26,32 +30,39 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
 import org.apache.camel.impl.transformer.TransformerKey;
 import org.apache.camel.model.transformer.TransformerDefinition;
 import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.Transformer;
 import org.apache.camel.spi.TransformerRegistry;
 import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.CompoundIterator;
 import org.apache.camel.util.LRUCache;
+import org.apache.camel.util.LRUCacheFactory;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ServiceHelper;
 
 /**
  * Default implementation of {@link org.apache.camel.spi.TransformerRegistry}.
  */
-public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transformer> implements TransformerRegistry<TransformerKey> {
+public class DefaultTransformerRegistry extends AbstractMap<TransformerKey, Transformer> implements TransformerRegistry<TransformerKey> {
+
     private static final long serialVersionUID = 1L;
-    private ConcurrentMap<TransformerKey, Transformer> staticMap;
-    private ConcurrentMap<TransformerKey, TransformerKey> aliasMap;
+    private Map<TransformerKey, Transformer> dynamicMap;
+    private Map<TransformerKey, Transformer> staticMap;
+    private Map<TransformerKey, TransformerKey> aliasMap;
     private final CamelContext context;
+    private int maxCacheSize;
 
     public DefaultTransformerRegistry(CamelContext context) throws Exception {
         this(context, new ArrayList<>());
     }
 
     public DefaultTransformerRegistry(CamelContext context, List<TransformerDefinition> definitions) throws Exception {
+        this.maxCacheSize = CamelContextHelper.getMaximumTransformerCacheSize(context);
         // do not stop on eviction, as the transformer may still be in use
-        super(CamelContextHelper.getMaximumTransformerCacheSize(context), CamelContextHelper.getMaximumTransformerCacheSize(context), false);
+        this.dynamicMap = LRUCacheFactory.newLRUCache(maxCacheSize, maxCacheSize, false);
         // static map to hold transformers we do not want to be evicted
         this.staticMap = new ConcurrentHashMap<>();
         this.aliasMap = new ConcurrentHashMap<>();
@@ -108,7 +119,9 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
 
     @Override
     public void start() throws Exception {
-        resetStatistics();
+        if (dynamicMap instanceof LRUCache) {
+            ((LRUCache) dynamicMap).resetStatistics();
+        }
     }
 
     @Override
@@ -116,9 +129,7 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
         // try static map first
         Transformer answer = staticMap.get(o);
         if (answer == null) {
-            answer = super.get(o);
-        } else {
-            hits.increment();
+            answer = dynamicMap.get(o);
         }
         return answer;
     }
@@ -133,10 +144,10 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
             return answer;
         }
 
-        answer = super.remove(key);
+        answer = dynamicMap.remove(key);
         if (answer != null) {
             // replace existing
-            super.put(key, transformer);
+            dynamicMap.put(key, transformer);
             return answer;
         }
 
@@ -144,33 +155,25 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
         if (context.isSetupRoutes() || context.isStartingRoutes()) {
             answer = staticMap.put(key, transformer);
         } else {
-            answer = super.put(key, transformer);
+            answer = dynamicMap.put(key, transformer);
         }
 
         return answer;
     }
 
     @Override
-    public void putAll(Map<? extends TransformerKey, ? extends Transformer> map) {
-        // need to use put instead of putAll to ensure the entries gets added to either static or dynamic map
-        for (Map.Entry<? extends TransformerKey, ? extends Transformer> entry : map.entrySet()) {
-            put(entry.getKey(), entry.getValue());
-        }
-    }
-
-    @Override
     public boolean containsKey(Object o) {
-        return staticMap.containsKey(o) || super.containsKey(o);
+        return staticMap.containsKey(o) || dynamicMap.containsKey(o);
     }
 
     @Override
     public boolean containsValue(Object o) {
-        return staticMap.containsValue(o) || super.containsValue(o);
+        return staticMap.containsValue(o) || dynamicMap.containsValue(o);
     }
 
     @Override
     public int size() {
-        return staticMap.size() + super.size();
+        return staticMap.size() + dynamicMap.size();
     }
 
     public int staticSize() {
@@ -179,19 +182,19 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
 
     @Override
     public int dynamicSize() {
-        return super.size();
+        return dynamicMap.size();
     }
 
     @Override
     public boolean isEmpty() {
-        return staticMap.isEmpty() && super.isEmpty();
+        return staticMap.isEmpty() && dynamicMap.isEmpty();
     }
 
     @Override
     public Transformer remove(Object o) {
         Transformer answer = staticMap.remove(o);
         if (answer == null) {
-            answer = super.remove(o);
+            answer = dynamicMap.remove(o);
         }
         return answer;
     }
@@ -199,36 +202,29 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
     @Override
     public void clear() {
         staticMap.clear();
-        super.clear();
-    }
-
-    @Override
-    public Set<TransformerKey> keySet() {
-        Set<TransformerKey> answer = new LinkedHashSet<>();
-        answer.addAll(staticMap.keySet());
-        answer.addAll(super.keySet());
-        return answer;
-    }
-
-    @Override
-    public Collection<Transformer> values() {
-        Collection<Transformer> answer = new ArrayList<>();
-        answer.addAll(staticMap.values());
-        answer.addAll(super.values());
-        return answer;
+        dynamicMap.clear();
     }
 
     @Override
     public Set<Entry<TransformerKey, Transformer>> entrySet() {
-        Set<Entry<TransformerKey, Transformer>> answer = new LinkedHashSet<>();
-        answer.addAll(staticMap.entrySet());
-        answer.addAll(super.entrySet());
-        return answer;
+        return new AbstractSet<Entry<TransformerKey, Transformer>>() {
+            @Override
+            public Iterator<Entry<TransformerKey, Transformer>> iterator() {
+                return new CompoundIterator<>(Arrays.asList(
+                        staticMap.entrySet().iterator(), dynamicMap.entrySet().iterator()
+                ));
+            }
+
+            @Override
+            public int size() {
+                return staticMap.size() + dynamicMap.size();
+            }
+        };
     }
 
     @Override
     public int getMaximumCacheSize() {
-        return super.getMaxCacheSize();
+        return maxCacheSize;
     }
 
     /**
@@ -241,6 +237,13 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
     }
 
     @Override
+    public void cleanUp() {
+        if (dynamicMap instanceof LRUCache) {
+            ((LRUCache) dynamicMap).cleanUp();
+        }
+    }
+
+    @Override
     public boolean isStatic(String scheme) {
         return staticMap.containsKey(new TransformerKey(scheme));
     }
@@ -252,24 +255,24 @@ public class DefaultTransformerRegistry extends LRUCache<TransformerKey, Transfo
 
     @Override
     public boolean isDynamic(String scheme) {
-        return super.containsKey(new TransformerKey(scheme));
+        return dynamicMap.containsKey(new TransformerKey(scheme));
     }
 
     @Override
     public boolean isDynamic(DataType from, DataType to) {
-        return super.containsKey(new TransformerKey(from, to));
+        return dynamicMap.containsKey(new TransformerKey(from, to));
     }
 
     @Override
     public void stop() throws Exception {
         ServiceHelper.stopServices(staticMap.values());
-        ServiceHelper.stopServices(values());
+        ServiceHelper.stopServices(dynamicMap.values());
         purge();
     }
 
     @Override
     public String toString() {
-        return "TransformerRegistry for " + context.getName() + ", capacity: " + getMaxCacheSize();
+        return "TransformerRegistry for " + context.getName() + ", capacity: " + maxCacheSize;
     }
 
     private TransformerKey createKey(TransformerDefinition def) {
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultValidatorRegistry.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultValidatorRegistry.java
index bcd91d7..e2b577c 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultValidatorRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultValidatorRegistry.java
@@ -16,14 +16,15 @@
  */
 package org.apache.camel.impl;
 
+import java.util.AbstractMap;
+import java.util.AbstractSet;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashSet;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.impl.validator.ValidatorKey;
@@ -32,25 +33,31 @@ import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.Validator;
 import org.apache.camel.spi.ValidatorRegistry;
 import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.CompoundIterator;
 import org.apache.camel.util.LRUCache;
+import org.apache.camel.util.LRUCacheFactory;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ServiceHelper;
 
 /**
  * Default implementation of {@link org.apache.camel.spi.ValidatorRegistry}.
  */
-public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator> implements ValidatorRegistry<ValidatorKey> {
+public class DefaultValidatorRegistry extends AbstractMap<ValidatorKey, Validator> implements ValidatorRegistry<ValidatorKey> {
+
     private static final long serialVersionUID = 1L;
-    private ConcurrentMap<ValidatorKey, Validator> staticMap;
+    private Map<ValidatorKey, Validator> dynamicMap;
+    private Map<ValidatorKey, Validator> staticMap;
     private final CamelContext context;
+    private int maxCacheSize;
 
     public DefaultValidatorRegistry(CamelContext context) throws Exception {
         this(context, new ArrayList<>());
     }
 
     public DefaultValidatorRegistry(CamelContext context, List<ValidatorDefinition> definitions) throws Exception {
+        this.maxCacheSize = CamelContextHelper.getMaximumValidatorCacheSize(context);
         // do not stop on eviction, as the validator may still be in use
-        super(CamelContextHelper.getMaximumValidatorCacheSize(context), CamelContextHelper.getMaximumValidatorCacheSize(context), false);
+        this.dynamicMap = LRUCacheFactory.newLRUCache(maxCacheSize, maxCacheSize, false);
         // static map to hold validator we do not want to be evicted
         this.staticMap = new ConcurrentHashMap<>();
         this.context = context;
@@ -72,7 +79,9 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
 
     @Override
     public void start() throws Exception {
-        resetStatistics();
+        if (dynamicMap instanceof LRUCache) {
+            ((LRUCache) dynamicMap).resetStatistics();
+        }
     }
 
     @Override
@@ -80,9 +89,7 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
         // try static map first
         Validator answer = staticMap.get(o);
         if (answer == null) {
-            answer = super.get(o);
-        } else {
-            hits.increment();
+            answer = dynamicMap.get(o);
         }
         return answer;
     }
@@ -97,10 +104,10 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
             return answer;
         }
 
-        answer = super.remove(key);
+        answer = dynamicMap.remove(key);
         if (answer != null) {
             // replace existing
-            super.put(key, validator);
+            dynamicMap.put(key, validator);
             return answer;
         }
 
@@ -108,33 +115,20 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
         if (context.isSetupRoutes() || context.isStartingRoutes()) {
             answer = staticMap.put(key, validator);
         } else {
-            answer = super.put(key, validator);
+            answer = dynamicMap.put(key, validator);
         }
 
         return answer;
     }
 
     @Override
-    public void putAll(Map<? extends ValidatorKey, ? extends Validator> map) {
-        // need to use put instead of putAll to ensure the entries gets added to either static or dynamic map
-        for (Map.Entry<? extends ValidatorKey, ? extends Validator> entry : map.entrySet()) {
-            put(entry.getKey(), entry.getValue());
-        }
-    }
-
-    @Override
     public boolean containsKey(Object o) {
-        return staticMap.containsKey(o) || super.containsKey(o);
+        return staticMap.containsKey(o) || dynamicMap.containsKey(o);
     }
 
     @Override
     public boolean containsValue(Object o) {
-        return staticMap.containsValue(o) || super.containsValue(o);
-    }
-
-    @Override
-    public int size() {
-        return staticMap.size() + super.size();
+        return staticMap.containsValue(o) || dynamicMap.containsValue(o);
     }
 
     public int staticSize() {
@@ -143,19 +137,19 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
 
     @Override
     public int dynamicSize() {
-        return super.size();
+        return dynamicMap.size();
     }
 
     @Override
     public boolean isEmpty() {
-        return staticMap.isEmpty() && super.isEmpty();
+        return staticMap.isEmpty() && dynamicMap.isEmpty();
     }
 
     @Override
     public Validator remove(Object o) {
         Validator answer = staticMap.remove(o);
         if (answer == null) {
-            answer = super.remove(o);
+            answer = dynamicMap.remove(o);
         }
         return answer;
     }
@@ -163,36 +157,29 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
     @Override
     public void clear() {
         staticMap.clear();
-        super.clear();
-    }
-
-    @Override
-    public Set<ValidatorKey> keySet() {
-        Set<ValidatorKey> answer = new LinkedHashSet<>();
-        answer.addAll(staticMap.keySet());
-        answer.addAll(super.keySet());
-        return answer;
-    }
-
-    @Override
-    public Collection<Validator> values() {
-        Collection<Validator> answer = new ArrayList<>();
-        answer.addAll(staticMap.values());
-        answer.addAll(super.values());
-        return answer;
+        dynamicMap.clear();
     }
 
     @Override
     public Set<Entry<ValidatorKey, Validator>> entrySet() {
-        Set<Entry<ValidatorKey, Validator>> answer = new LinkedHashSet<>();
-        answer.addAll(staticMap.entrySet());
-        answer.addAll(super.entrySet());
-        return answer;
+        return new AbstractSet<Entry<ValidatorKey, Validator>>() {
+            @Override
+            public Iterator<Entry<ValidatorKey, Validator>> iterator() {
+                return new CompoundIterator<>(Arrays.asList(
+                        staticMap.entrySet().iterator(), dynamicMap.entrySet().iterator()
+                ));
+            }
+
+            @Override
+            public int size() {
+                return staticMap.size() + dynamicMap.size();
+            }
+        };
     }
 
     @Override
     public int getMaximumCacheSize() {
-        return super.getMaxCacheSize();
+        return maxCacheSize;
     }
 
     /**
@@ -201,7 +188,14 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
     @Override
     public void purge() {
         // only purge the dynamic part
-        super.clear();
+        dynamicMap.clear();
+    }
+
+    @Override
+    public void cleanUp() {
+        if (dynamicMap instanceof LRUCache) {
+            ((LRUCache) dynamicMap).cleanUp();
+        }
     }
 
     @Override
@@ -217,13 +211,13 @@ public class DefaultValidatorRegistry extends LRUCache<ValidatorKey, Validator>
     @Override
     public void stop() throws Exception {
         ServiceHelper.stopServices(staticMap.values());
-        ServiceHelper.stopServices(values());
+        ServiceHelper.stopServices(dynamicMap.values());
         purge();
     }
 
     @Override
     public String toString() {
-        return "ValidatorRegistry for " + context.getName() + ", capacity: " + getMaxCacheSize();
+        return "ValidatorRegistry for " + context.getName() + ", capacity: " + maxCacheSize;
     }
 
 }
diff --git a/camel-core/src/main/java/org/apache/camel/impl/ProducerCache.java b/camel-core/src/main/java/org/apache/camel/impl/ProducerCache.java
index cb3ddae..4e3f4f5 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/ProducerCache.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/ProducerCache.java
@@ -136,7 +136,7 @@ public class ProducerCache extends ServiceSupport {
      * @return the cache
      */
     @SuppressWarnings("unchecked")
-    protected static LRUCache<String, Producer> createLRUCache(int cacheSize) {
+    protected static Map<String, Producer> createLRUCache(int cacheSize) {
         // Use a regular cache as we want to ensure that the lifecycle of the producers
         // being cache is properly handled, such as they are stopped when being evicted
         // or when this cache is stopped. This is needed as some producers requires to
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 21f6658..5523604 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
@@ -51,7 +51,6 @@ import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.support.ServiceSupport;
 import org.apache.camel.util.CamelLogger;
 import org.apache.camel.util.LRUCacheFactory;
-import org.apache.camel.util.LRUSoftCache;
 import org.apache.camel.util.MessageHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
@@ -69,7 +68,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     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 LRUSoftCache<TypeMapping, TypeMapping> misses = LRUCacheFactory.newLRUSoftCache(1000);
+    protected final Map<TypeMapping, TypeMapping> misses = LRUCacheFactory.newLRUSoftCache(1000);
     protected final List<TypeConverterLoader> typeConverterLoaders = new ArrayList<>();
     protected final List<FallbackTypeConverter> fallbackConverters = new CopyOnWriteArrayList<>();
     protected final PackageScanClassResolver resolver;
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java
index 9787bf9..5b866d6 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java
@@ -18,6 +18,7 @@ package org.apache.camel.language.simple;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.camel.Expression;
@@ -32,7 +33,6 @@ import org.apache.camel.language.simple.types.SimpleIllegalSyntaxException;
 import org.apache.camel.language.simple.types.SimpleParserException;
 import org.apache.camel.language.simple.types.SimpleToken;
 import org.apache.camel.language.simple.types.TokenType;
-import org.apache.camel.util.LRUCache;
 
 /**
  * A parser to parse simple language as a Camel {@link Expression}
@@ -40,7 +40,7 @@ import org.apache.camel.util.LRUCache;
 public class SimpleExpressionParser extends BaseSimpleParser {
 
     // use caches to avoid re-parsing the same expressions over and over again
-    private LRUCache<String, Expression> cacheExpression;
+    private Map<String, Expression> cacheExpression;
 
     @Deprecated
     public SimpleExpressionParser(String expression) {
@@ -53,7 +53,7 @@ public class SimpleExpressionParser extends BaseSimpleParser {
     }
 
     public SimpleExpressionParser(String expression, boolean allowEscape,
-                                  LRUCache<String, Expression> cacheExpression) {
+                                  Map<String, Expression> cacheExpression) {
         super(expression, allowEscape);
         this.cacheExpression = cacheExpression;
     }
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
index 94f952e..059ecf3 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.language.simple;
 
+import java.util.Map;
+
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
 import org.apache.camel.StaticService;
@@ -104,8 +106,8 @@ public class SimpleLanguage extends LanguageSupport implements StaticService {
     boolean allowEscape = true;
 
     // use caches to avoid re-parsing the same expressions over and over again
-    private LRUCache<String, Expression> cacheExpression;
-    private LRUCache<String, Predicate> cachePredicate;
+    private Map<String, Expression> cacheExpression;
+    private Map<String, Predicate> cachePredicate;
 
     /**
      * Default constructor.
@@ -131,16 +133,18 @@ public class SimpleLanguage extends LanguageSupport implements StaticService {
 
     @Override
     public void stop() throws Exception {
-        if (cachePredicate != null) {
+        if (cachePredicate instanceof LRUCache) {
             if (LOG.isDebugEnabled()) {
+                LRUCache cache = (LRUCache) cachePredicate;
                 LOG.debug("Clearing simple language predicate cache[size={}, hits={}, misses={}, evicted={}]",
-                    cachePredicate.size(), cachePredicate.getHits(), cachePredicate.getMisses(), cachePredicate.getEvicted());
+                        cache.size(), cache.getHits(), cache.getMisses(), cache.getEvicted());
             }
         }
-        if (cacheExpression != null) {
+        if (cacheExpression instanceof LRUCache) {
             if (LOG.isDebugEnabled()) {
+                LRUCache cache = (LRUCache) cacheExpression;
                 LOG.debug("Clearing simple language expression cache[size={}, hits={}, misses={}, evicted={}]",
-                    cacheExpression.size(), cacheExpression.getHits(), cacheExpression.getMisses(), cacheExpression.getEvicted());
+                        cache.size(), cache.getHits(), cache.getMisses(), cache.getEvicted());
             }
         }
     }
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/SimplePredicateParser.java b/camel-core/src/main/java/org/apache/camel/language/simple/SimplePredicateParser.java
index 6d381e8..a41e9cc 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/SimplePredicateParser.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/SimplePredicateParser.java
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.Expression;
@@ -55,7 +56,7 @@ import org.apache.camel.util.LRUCache;
 public class SimplePredicateParser extends BaseSimpleParser {
 
     // use caches to avoid re-parsing the same expressions over and over again
-    private LRUCache<String, Expression> cacheExpression;
+    private Map<String, Expression> cacheExpression;
 
     @Deprecated
     public SimplePredicateParser(String expression) {
@@ -67,7 +68,7 @@ public class SimplePredicateParser extends BaseSimpleParser {
         super(expression, allowEscape);
     }
 
-    public SimplePredicateParser(String expression, boolean allowEscape, LRUCache<String, Expression> cacheExpression) {
+    public SimplePredicateParser(String expression, boolean allowEscape, Map<String, Expression> cacheExpression) {
         super(expression, allowEscape);
         this.cacheExpression = cacheExpression;
     }
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index b3c5674..acf6106 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.language.simple.ast;
 
+import java.util.Map;
+
 import org.apache.camel.Expression;
 import org.apache.camel.builder.ExpressionBuilder;
 import org.apache.camel.language.simple.types.SimpleParserException;
@@ -32,14 +34,14 @@ import org.apache.camel.util.StringHelper;
 public class SimpleFunctionExpression extends LiteralExpression {
 
     // use caches to avoid re-parsing the same expressions over and over again
-    private LRUCache<String, Expression> cacheExpression;
+    private Map<String, Expression> cacheExpression;
 
     @Deprecated
     public SimpleFunctionExpression(SimpleToken token) {
         super(token);
     }
 
-    public SimpleFunctionExpression(SimpleToken token, LRUCache<String, Expression> cacheExpression) {
+    public SimpleFunctionExpression(SimpleToken token, Map<String, Expression> cacheExpression) {
         super(token);
         this.cacheExpression = cacheExpression;
     }
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
index 5198789..e387b87 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.language.simple.ast;
 
+import java.util.Map;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.language.simple.types.SimpleIllegalSyntaxException;
@@ -30,10 +32,10 @@ import org.apache.camel.util.StringHelper;
 public class SimpleFunctionStart extends BaseSimpleNode implements BlockStart {
 
     // use caches to avoid re-parsing the same expressions over and over again
-    private final LRUCache<String, Expression> cacheExpression;
+    private final Map<String, Expression> cacheExpression;
     private final CompositeNodes block;
 
-    public SimpleFunctionStart(SimpleToken token, LRUCache<String, Expression> cacheExpression) {
+    public SimpleFunctionStart(SimpleToken token, Map<String, Expression> cacheExpression) {
         super(token);
         this.block = new CompositeNodes(token);
         this.cacheExpression = cacheExpression;
diff --git a/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java b/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java
index f96602f..f27bbdd 100644
--- a/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java
+++ b/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java
@@ -57,7 +57,7 @@ public class MBeanInfoAssembler implements Service {
     // use a cache to speedup gathering JMX MBeanInfo for known classes
     // use a weak cache as we dont want the cache to keep around as it reference classes
     // which could prevent classloader to unload classes if being referenced from this cache
-    private LRUCache<Class<?>, MBeanAttributesAndOperations> cache;
+    private Map<Class<?>, MBeanAttributesAndOperations> cache;
 
     public MBeanInfoAssembler() {
     }
@@ -75,7 +75,8 @@ public class MBeanInfoAssembler implements Service {
     @Override
     public void stop() throws Exception {
         if (cache != null) {
-            if (LOG.isDebugEnabled()) {
+            if (LOG.isDebugEnabled() && cache instanceof LRUCache) {
+                LRUCache cache = (LRUCache) this.cache;
                 LOG.debug("Clearing cache[size={}, hits={}, misses={}, evicted={}]", new Object[]{cache.size(), cache.getHits(), cache.getMisses(), cache.getEvicted()});
             }
             cache.clear();
diff --git a/camel-core/src/main/java/org/apache/camel/util/CompoundIterator.java b/camel-core/src/main/java/org/apache/camel/util/CompoundIterator.java
new file mode 100644
index 0000000..9f372c3
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/util/CompoundIterator.java
@@ -0,0 +1,64 @@
+/**
+ * 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.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Compound iterator to iterate over multiple iterators sequentially.
+ */
+public class CompoundIterator<T> implements Iterator<T> {
+
+    final Iterator<Iterator<T>> it;
+    Iterator<T> current;
+
+    public CompoundIterator(Iterable<Iterator<T>> it) {
+        this(it.iterator());
+    }
+
+    public CompoundIterator(Iterator<Iterator<T>> it) {
+        this.it = it;
+        this.current = it.hasNext() ? it.next() : null;
+    }
+
+    @Override
+    public boolean hasNext() {
+        while (current != null) {
+            if (current.hasNext()) {
+                return true;
+            } else {
+                current = it.hasNext() ? it.next() : null;
+            }
+
+        }
+        return false;
+    }
+
+    @Override
+    public T next() {
+        if (current != null) {
+            return current.next();
+        }
+        throw new NoSuchElementException();
+    }
+
+    @Override
+    public void remove() {
+        current.remove();
+    }
+}
diff --git a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
index 02c2d7a..5445816 100644
--- a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
@@ -68,7 +68,7 @@ public final class IntrospectionSupport {
     // use a weak cache as we dont want the cache to keep around as it reference classes
     // which could prevent classloader to unload classes if being referenced from this cache
     @SuppressWarnings("unchecked")
-    private static final LRUCache<Class<?>, ClassInfo> CACHE = LRUCacheFactory.newLRUWeakCache(1000);
+    private static final Map<Class<?>, ClassInfo> CACHE = LRUCacheFactory.newLRUWeakCache(1000);
     private static final Object LOCK = new Object();
     private static final Pattern SECRETS = Pattern.compile(".*(passphrase|password|secretKey).*", Pattern.CASE_INSENSITIVE);
 
@@ -132,7 +132,8 @@ public final class IntrospectionSupport {
      * This implementation will clear its introspection cache.
      */
     public static void stop() {
-        if (LOG.isDebugEnabled()) {
+        if (LOG.isDebugEnabled() && CACHE instanceof LRUCache) {
+            LRUCache CACHE = (LRUCache) IntrospectionSupport.CACHE;
             LOG.debug("Clearing cache[size={}, hits={}, misses={}, evicted={}]", new Object[]{CACHE.size(), CACHE.getHits(), CACHE.getMisses(), CACHE.getEvicted()});
         }
         CACHE.clear();
diff --git a/camel-core/src/main/java/org/apache/camel/util/LRUCacheFactory.java b/camel-core/src/main/java/org/apache/camel/util/LRUCacheFactory.java
index 9b7498e..e221bd5 100644
--- a/camel-core/src/main/java/org/apache/camel/util/LRUCacheFactory.java
+++ b/camel-core/src/main/java/org/apache/camel/util/LRUCacheFactory.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.util;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.util.concurrent.ThreadHelper;
@@ -31,9 +33,24 @@ public final class LRUCacheFactory {
 
     private static final AtomicBoolean INIT = new AtomicBoolean();
 
+    private static final boolean USE_SIMPLE_CACHE;
+
     private LRUCacheFactory() {
     }
 
+    static {
+        USE_SIMPLE_CACHE = "true".equalsIgnoreCase(System.getProperty("CamelSimpleLRUCacheFactory", "false"));
+        if (!USE_SIMPLE_CACHE) {
+            boolean warmUp = "true".equalsIgnoreCase(System.getProperty("CamelWarmUpLRUCacheFactory", "true"));
+            if (warmUp) {
+                // warm-up LRUCache which happens in a background test, which can speedup starting Camel
+                // as the warm-up can run concurrently with starting up Camel and the runtime container Camel may be running inside
+                warmUp();
+            }
+        }
+    }
+
+
     /**
      * Warm-up the LRUCache to startup Apache Camel faster.
      */
@@ -64,9 +81,12 @@ public final class LRUCacheFactory {
      * @param maximumCacheSize the max capacity.
      * @throws IllegalArgumentException if the initial capacity is negative
      */
-    public static LRUCache newLRUCache(int maximumCacheSize) {
+    public static <K, V> Map<K, V> newLRUCache(int maximumCacheSize) {
         LOG.trace("Creating LRUCache with maximumCacheSize: {}", maximumCacheSize);
-        return new LRUCache(maximumCacheSize);
+        if (USE_SIMPLE_CACHE) {
+            return new SimpleLRUCache<>(maximumCacheSize);
+        }
+        return new LRUCache<>(maximumCacheSize);
     }
 
     /**
@@ -77,9 +97,12 @@ public final class LRUCacheFactory {
      * @param maximumCacheSize the max capacity.
      * @throws IllegalArgumentException if the initial capacity is negative
      */
-    public static LRUCache newLRUCache(int initialCapacity, int maximumCacheSize) {
+    public static <K, V> Map<K, V> newLRUCache(int initialCapacity, int maximumCacheSize) {
         LOG.trace("Creating LRUCache with initialCapacity: {}, maximumCacheSize: {}", initialCapacity, maximumCacheSize);
-        return new LRUCache(initialCapacity, maximumCacheSize);
+        if (USE_SIMPLE_CACHE) {
+            return new SimpleLRUCache<>(initialCapacity, maximumCacheSize);
+        }
+        return new LRUCache<>(initialCapacity, maximumCacheSize);
     }
 
     /**
@@ -91,9 +114,12 @@ public final class LRUCacheFactory {
      * @param stopOnEviction   whether to stop service on eviction.
      * @throws IllegalArgumentException if the initial capacity is negative
      */
-    public static LRUCache newLRUCache(int initialCapacity, int maximumCacheSize, boolean stopOnEviction) {
+    public static <K, V> Map<K, V> newLRUCache(int initialCapacity, int maximumCacheSize, boolean stopOnEviction) {
         LOG.trace("Creating LRUCache with initialCapacity: {}, maximumCacheSize: {}, stopOnEviction: {}", initialCapacity, maximumCacheSize, stopOnEviction);
-        return new LRUCache(initialCapacity, maximumCacheSize, stopOnEviction);
+        if (USE_SIMPLE_CACHE) {
+            return new SimpleLRUCache<>(initialCapacity, maximumCacheSize, stopOnEviction);
+        }
+        return new LRUCache<>(initialCapacity, maximumCacheSize, stopOnEviction);
     }
 
     /**
@@ -103,9 +129,12 @@ public final class LRUCacheFactory {
      * @param maximumCacheSize the max capacity.
      * @throws IllegalArgumentException if the initial capacity is negative
      */
-    public static LRUSoftCache newLRUSoftCache(int maximumCacheSize) {
+    public static <K, V> Map<K, V> newLRUSoftCache(int maximumCacheSize) {
         LOG.trace("Creating LRUSoftCache with maximumCacheSize: {}", maximumCacheSize);
-        return new LRUSoftCache(maximumCacheSize);
+        if (USE_SIMPLE_CACHE) {
+            return new SimpleLRUCache<>(maximumCacheSize);
+        }
+        return new LRUSoftCache<>(maximumCacheSize);
     }
 
     /**
@@ -115,8 +144,51 @@ public final class LRUCacheFactory {
      * @param maximumCacheSize the max capacity.
      * @throws IllegalArgumentException if the initial capacity is negative
      */
-    public static LRUWeakCache newLRUWeakCache(int maximumCacheSize) {
+    public static <K, V> Map<K, V> newLRUWeakCache(int maximumCacheSize) {
         LOG.trace("Creating LRUWeakCache with maximumCacheSize: {}", maximumCacheSize);
-        return new LRUWeakCache(maximumCacheSize);
+        if (USE_SIMPLE_CACHE) {
+            return new SimpleLRUCache<>(maximumCacheSize);
+        }
+        return new LRUWeakCache<>(maximumCacheSize);
     }
+
+    private static class SimpleLRUCache<K, V> extends LinkedHashMap<K, V> {
+
+        static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+        private final int maximumCacheSize;
+        private final boolean stopOnEviction;
+
+        public SimpleLRUCache(int maximumCacheSize) {
+            this(16, maximumCacheSize, maximumCacheSize > 0);
+        }
+
+        public SimpleLRUCache(int initialCapacity, int maximumCacheSize) {
+            this(initialCapacity, maximumCacheSize, maximumCacheSize > 0);
+        }
+
+        public SimpleLRUCache(int initialCapacity, int maximumCacheSize, boolean stopOnEviction) {
+            super(initialCapacity, DEFAULT_LOAD_FACTOR, true);
+            this.maximumCacheSize = maximumCacheSize;
+            this.stopOnEviction = stopOnEviction;
+        }
+
+        @Override
+        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+            if (size() >= maximumCacheSize) {
+                if (stopOnEviction) {
+                    Object value = eldest.getValue();
+                    try {
+                        // stop service as its evicted from cache
+                        ServiceHelper.stopService(value);
+                    } catch (Exception e) {
+                        LOG.warn("Error stopping service: " + value + ". This exception will be ignored.", e);
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+    }
+
 }
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java
index a9531af..f92a12a 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java
@@ -17,10 +17,10 @@
 package org.apache.camel.component.sql.stored;
 
 import java.sql.SQLException;
+import java.util.Map;
 
 import org.apache.camel.component.sql.stored.template.TemplateParser;
 import org.apache.camel.support.ServiceSupport;
-import org.apache.camel.util.LRUCache;
 import org.apache.camel.util.LRUCacheFactory;
 import org.springframework.jdbc.core.JdbcTemplate;
 
@@ -37,9 +37,9 @@ public class CallableStatementWrapperFactory extends ServiceSupport {
     boolean function;
 
     @SuppressWarnings("unchecked")
-    private final LRUCache<String, TemplateStoredProcedure> templateCache = LRUCacheFactory.newLRUCache(TEMPLATE_CACHE_DEFAULT_SIZE);
+    private final Map<String, TemplateStoredProcedure> templateCache = LRUCacheFactory.newLRUCache(TEMPLATE_CACHE_DEFAULT_SIZE);
     @SuppressWarnings("unchecked")
-    private final LRUCache<String, BatchCallableStatementCreatorFactory> batchTemplateCache = LRUCacheFactory.newLRUCache(BATCH_TEMPLATE_CACHE_DEFAULT_SIZE);
+    private final Map<String, BatchCallableStatementCreatorFactory> batchTemplateCache = LRUCacheFactory.newLRUCache(BATCH_TEMPLATE_CACHE_DEFAULT_SIZE);
 
     public CallableStatementWrapperFactory(JdbcTemplate jdbcTemplate, TemplateParser templateParser, boolean function) {
         this.jdbcTemplate = jdbcTemplate;


[camel] 05/05: [CAMEL-12688] Generate a fallback converter containing all core converters for performances

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

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 0a88d1366ebde37bb5973704dd88ee723c005209
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon Jun 25 15:22:46 2018 +0200

    [CAMEL-12688] Generate a fallback converter containing all core converters for performances
---
 .../apache/camel/tools/apt/ConverterProcessor.java | 198 +++++++++++++++++++++
 .../services/javax.annotation.processing.Processor |   1 +
 2 files changed, 199 insertions(+)

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
new file mode 100644
index 0000000..ac372e1
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ConverterProcessor.java
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.tools.apt;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.annotation.processing.AbstractProcessor;
+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.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.JavaFileObject;
+
+@SupportedAnnotationTypes({"org.apache.camel.Converter"})
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
+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) {
+                return false;
+            }
+
+            if (roundEnv.processingOver()) {
+                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)) {
+                if (element.getKind() == ElementKind.METHOD) {
+                    ExecutableElement ee = (ExecutableElement) element;
+                    TypeMirror to = ee.getReturnType();
+                    TypeMirror from = ee.getParameters().get(0).asType();
+                    String fromStr = toString(from);
+                    if (!fromStr.endsWith("[]")) {
+                        TypeElement e = this.processingEnv.getElementUtils().getTypeElement(fromStr);
+                        if (e != null) {
+                            from = e.asType();
+                        } else {
+                            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Could not retrieve type element for " + fromStr);
+                        }
+
+                    }
+                    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;
+            }
+
+            String p = "org.apache.camel.impl.converter";
+            String c = "CoreFallbackConverter";
+            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("\n");
+                writer.append("@SuppressWarnings(\"unchecked\")\n");
+                writer.append("public class ").append(c).append(" extends TypeConverterSupport {\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("        }\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");
+                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");
+                        }
+                        writer.append("                    return ").append(toJava(from.getValue(), converterClasses)).append(";\n");
+                        writer.append("                }\n");
+                    }
+                    writer.append("                break;\n");
+                    writer.append("            }\n");
+                }
+                writer.append("        }\n");
+                writer.append("        return null;\n");
+                writer.append("    }\n");
+
+                for (String f : converterClasses) {
+                    String s = f.substring(f.lastIndexOf('.') + 1);
+                    String v = s.substring(0, 1).toLowerCase() + s.substring(1);
+                    writer.append("    private volatile ").append(f).append(" ").append(v).append(";\n");
+                    writer.append("    private ").append(f).append(" get").append(s).append("() {\n");
+                    writer.append("        if (").append(v).append(" == null) {\n");
+                    writer.append("            synchronized (this) {\n");
+                    writer.append("                if (").append(v).append(" == null) {\n");
+                    writer.append("                    ").append(v).append(" = new ").append(f).append("();\n");
+                    writer.append("                }\n");
+                    writer.append("            }\n");
+                    writer.append("        }\n");
+                    writer.append("        return ").append(v).append(";\n");
+                    writer.append("    }\n");
+                }
+
+                writer.append("}\n");
+                writer.flush();
+            }
+
+        } catch (Throwable e) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Unable to process elements annotated with @UriEndpoint: " + e.getMessage());
+            dumpExceptionToErrorFile("camel-apt-error.log", "Error processing @Converter", e);
+        }
+        return false;
+    }
+
+    private String toString(TypeMirror type) {
+        return type.toString().replaceAll("<.*>", "");
+    }
+
+    private String toJava(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(0).asType());
+        String cast = type.equals("java.lang.Object") ? "" : "(" + type + ") ";
+        return pfx + "(" + cast + "value" + (converter.getParameters().size() == 2 ? ", exchange" : "") + ")";
+    }
+
+    public static void dumpExceptionToErrorFile(String fileName, String message, Throwable e) {
+        File file = new File(fileName);
+        try {
+            FileOutputStream fos = new FileOutputStream(file);
+            StringWriter sw = new StringWriter();
+            PrintWriter pw = new PrintWriter(sw);
+            e.printStackTrace(pw);
+            fos.write(message.getBytes());
+            fos.write("\n\n".getBytes());
+            fos.write(sw.toString().getBytes());
+            pw.close();
+            sw.close();
+            fos.close();
+        } catch (Throwable t) {
+            // ignore
+        }
+    }
+
+}
diff --git a/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index 065c7b0..85b35af 100644
--- a/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -18,3 +18,4 @@
 ### only specify ModelAnnotationProcessor as it delegates to CoreEip or Spring accordingly
 org.apache.camel.tools.apt.ModelAnnotationProcessor
 org.apache.camel.tools.apt.EndpointAnnotationProcessor
+org.apache.camel.tools.apt.ConverterProcessor


[camel] 02/05: [CAMEL-12688] Avoid lamba

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

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9fc335ffa767df4cf06c5127733518758c2c8fda
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Sat Jun 23 01:19:15 2018 +0200

    [CAMEL-12688] Avoid lamba
---
 .../org/apache/camel/impl/DefaultCamelContext.java | 33 +++++++++++++++-------
 .../apache/camel/impl/DefaultFactoryFinder.java    | 29 ++++++++++++-------
 2 files changed, 42 insertions(+), 20 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index d081cae..8adcc18 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -42,6 +42,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
@@ -461,9 +462,12 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
             final AtomicBoolean created = new AtomicBoolean(false);
 
             // atomic operation to get/create a component. Avoid global locks.
-            final Component component = components.computeIfAbsent(name, comp -> {
-                created.set(true);
-                return initComponent(name, autoCreateComponents);
+            final Component component = components.computeIfAbsent(name, new Function<String, Component>() {
+                @Override
+                public Component apply(String comp) {
+                    created.set(true);
+                    return DefaultCamelContext.this.initComponent(name, autoCreateComponents);
+                }
             });
 
             // Start the component after its creation as if it is a component proxy
@@ -3267,7 +3271,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         }
     }
 
-    private void doStartCamel() throws Exception {
+    protected void doStartCamel() throws Exception {
 
         // custom properties may use property placeholders so resolve those early on
         if (globalOptions != null && !globalOptions.isEmpty()) {
@@ -3507,13 +3511,22 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         // shutdown await manager to trigger interrupt of blocked threads to attempt to free these threads graceful
         shutdownServices(asyncProcessorAwaitManager);
 
-        shutdownServices(getRouteStartupOrder().stream()
-            .sorted(Comparator.comparing(RouteStartupOrder::getStartupOrder).reversed())
-            .map(DefaultRouteStartupOrder.class::cast)
-            .map(DefaultRouteStartupOrder::getRouteService)
-            .collect(Collectors.toList()), false);
+        routeStartupOrder.sort(new Comparator<RouteStartupOrder>() {
+            @Override
+            public int compare(RouteStartupOrder o1, RouteStartupOrder o2) {
+                // Reversed order
+                return Integer.compare(o2.getStartupOrder(), o1.getStartupOrder());
+            }
+        });
+        List<RouteService> list = new ArrayList<>();
+        for (RouteStartupOrder startupOrder : routeStartupOrder) {
+            DefaultRouteStartupOrder order = (DefaultRouteStartupOrder) startupOrder;
+            RouteService routeService = order.getRouteService();
+            list.add(routeService);
+        }
+        shutdownServices(list, false);
         // do not clear route services or startup listeners as we can start Camel again and get the route back as before
-        getRouteStartupOrder().clear();
+        routeStartupOrder.clear();
 
         // but clear any suspend routes
         suspendedRouteServices.clear();
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
index bf87c6e..3ed501e 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
 
 import org.apache.camel.NoFactoryAvailableException;
 import org.apache.camel.spi.ClassResolver;
@@ -79,7 +80,12 @@ public class DefaultFactoryFinder implements FactoryFinder {
         final String prefix = propertyPrefix != null ? propertyPrefix : "";
         final String classKey = prefix + key;
 
-        return addToClassMap(classKey, () -> newInstance(doFindFactoryProperties(key), prefix));
+        return addToClassMap(classKey, new ClassSupplier() {
+            @Override
+            public Class<?> get() throws ClassNotFoundException, IOException {
+                return DefaultFactoryFinder.this.newInstance(DefaultFactoryFinder.this.doFindFactoryProperties(key), prefix);
+            }
+        });
     }
 
     @Override
@@ -160,15 +166,18 @@ public class DefaultFactoryFinder implements FactoryFinder {
      */
     protected Class<?> addToClassMap(String key, ClassSupplier mappingFunction) throws ClassNotFoundException, IOException {
         try {
-            return classMap.computeIfAbsent(key, (String classKey) -> {
-                try {
-                    return mappingFunction.get();
-                } catch (ClassNotFoundException e) {
-                    throw new WrappedRuntimeException(e);
-                } catch (NoFactoryAvailableException e) {
-                    throw new WrappedRuntimeException(e);
-                } catch (IOException e) {
-                    throw new WrappedRuntimeException(e);
+            return classMap.computeIfAbsent(key, new Function<String, Class<?>>() {
+                @Override
+                public Class<?> apply(String classKey) {
+                    try {
+                        return mappingFunction.get();
+                    } catch (ClassNotFoundException e) {
+                        throw new WrappedRuntimeException(e);
+                    } catch (NoFactoryAvailableException e) {
+                        throw new WrappedRuntimeException(e);
+                    } catch (IOException e) {
+                        throw new WrappedRuntimeException(e);
+                    }
                 }
             });
         } catch (WrappedRuntimeException e) {


[camel] 03/05: [CAMEL-12688] Improve Scanner performances

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

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 0e9830d227b433f8975ce93a4882e7fa04725f02
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Sat Jun 23 22:58:15 2018 +0200

    [CAMEL-12688] Improve Scanner performances
---
 .../apache/camel/builder/ExpressionBuilder.java    |  11 +-
 .../camel/component/dataset/FileDataSet.java       |   8 +-
 .../org/apache/camel/impl/FileStateRepository.java |  15 +-
 .../java/org/apache/camel/processor/Splitter.java  |  15 +-
 .../idempotent/FileIdempotentRepository.java       |  42 +--
 .../camel/support/TokenPairExpressionIterator.java |   4 +-
 .../support/TokenXMLPairExpressionIterator.java    |   4 +-
 .../java/org/apache/camel/util/GroupIterator.java  |  13 +-
 .../org/apache/camel/util/GroupTokenIterator.java  |  14 +-
 .../main/java/org/apache/camel/util/IOHelper.java  |  23 ++
 .../java/org/apache/camel/util/ObjectHelper.java   |  59 ++--
 .../main/java/org/apache/camel/util/Scanner.java   | 303 +++++++++++++++++++++
 .../java/org/apache/camel/util/SkipIterator.java   |  14 +-
 .../apache/camel/util/GroupTokenIteratorTest.java  |  11 +-
 14 files changed, 390 insertions(+), 146 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
index 3641d0f..11f640b 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
@@ -27,7 +27,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.Set;
 import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicReference;
@@ -1558,8 +1558,7 @@ public final class ExpressionBuilder {
             public Object evaluate(Exchange exchange) {
                 String text = simpleExpression(token).evaluate(exchange, String.class);
                 Object value = expression.evaluate(exchange, Object.class);
-                Scanner scanner = ObjectHelper.getScanner(exchange, value);
-                scanner.useDelimiter(text);
+                Scanner scanner = ObjectHelper.getScanner(exchange, value, text);
                 return scanner;
             }
 
@@ -1625,18 +1624,16 @@ public final class ExpressionBuilder {
      */
     public static Expression regexTokenizeExpression(final Expression expression,
                                                      final String regexTokenizer) {
-        final Pattern pattern = Pattern.compile(regexTokenizer);
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
                 Object value = expression.evaluate(exchange, Object.class);
-                Scanner scanner = ObjectHelper.getScanner(exchange, value);
-                scanner.useDelimiter(pattern);
+                Scanner scanner = ObjectHelper.getScanner(exchange, value, regexTokenizer);
                 return scanner;
             }
 
             @Override
             public String toString() {
-                return "regexTokenize(" + expression + ", " + pattern.pattern() + ")";
+                return "regexTokenize(" + expression + ", " + regexTokenizer + ")";
             }
         };
     }
diff --git a/camel-core/src/main/java/org/apache/camel/component/dataset/FileDataSet.java b/camel-core/src/main/java/org/apache/camel/component/dataset/FileDataSet.java
index 24f263d..1551035 100644
--- a/camel-core/src/main/java/org/apache/camel/component/dataset/FileDataSet.java
+++ b/camel-core/src/main/java/org/apache/camel/component/dataset/FileDataSet.java
@@ -22,7 +22,9 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Scanner;
+
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.Scanner;
 
 /**
  * A DataSet that reads payloads from a file that are used to create each message exchange
@@ -80,9 +82,7 @@ public class FileDataSet extends ListDataSet {
 
     private void readSourceFile() throws IOException {
         List<Object> bodies = new LinkedList<>();
-        try (BufferedReader br = new BufferedReader(new FileReader(sourceFile))) {
-            Scanner scanner = new Scanner(br);
-            scanner.useDelimiter(delimiter);
+        try (Scanner scanner = new Scanner(sourceFile, null, delimiter)) {
             while (scanner.hasNext()) {
                 String nextPayload = scanner.next();
                 if ((nextPayload != null)  &&  (nextPayload.length() > 0)) {
diff --git a/camel-core/src/main/java/org/apache/camel/impl/FileStateRepository.java b/camel-core/src/main/java/org/apache/camel/impl/FileStateRepository.java
index efbd068..bac7f95 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/FileStateRepository.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/FileStateRepository.java
@@ -21,7 +21,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.api.management.ManagedAttribute;
@@ -217,12 +217,9 @@ public class FileStateRepository extends ServiceSupport implements StateReposito
         LOG.trace("Loading to 1st level cache from state filestore: {}", fileStore);
 
         cache.clear();
-        Scanner scanner = null;
-        try {
-            scanner = new Scanner(fileStore);
-            scanner.useDelimiter(STORE_DELIMITER);
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine();
+        try (Scanner scanner = new Scanner(fileStore, null, STORE_DELIMITER)) {
+            while (scanner.hasNext()) {
+                String line = scanner.next();
                 int separatorIndex = line.indexOf(KEY_VALUE_DELIMITER);
                 String key = line.substring(0, separatorIndex);
                 String value = line.substring(separatorIndex + KEY_VALUE_DELIMITER.length());
@@ -230,10 +227,6 @@ public class FileStateRepository extends ServiceSupport implements StateReposito
             }
         } catch (IOException e) {
             throw ObjectHelper.wrapRuntimeCamelException(e);
-        } finally {
-            if (scanner != null) {
-                scanner.close();
-            }
         }
 
         LOG.debug("Loaded {} to the 1st level cache from state filestore: {}", cache.size(), fileStore);
diff --git a/camel-core/src/main/java/org/apache/camel/processor/Splitter.java b/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
index 2a50bc6..6eb6833 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
@@ -23,7 +23,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.concurrent.ExecutorService;
 
 import org.apache.camel.AsyncCallback;
@@ -230,18 +230,7 @@ public class Splitter extends MulticastProcessor implements AsyncProcessor, Trac
 
         @Override
         public void close() throws IOException {
-            if (value instanceof Scanner) {
-                // special for Scanner which implement the Closeable since JDK7 
-                Scanner scanner = (Scanner) value;
-                scanner.close();
-                IOException ioException = scanner.ioException();
-                if (ioException != null) {
-                    throw ioException;
-                }
-            } else if (value instanceof Closeable) {
-                // we should throw out the exception here   
-                IOHelper.closeWithException((Closeable) value);
-            }
+            IOHelper.closeIterator(value);
         }
        
     }
diff --git a/camel-core/src/main/java/org/apache/camel/processor/idempotent/FileIdempotentRepository.java b/camel-core/src/main/java/org/apache/camel/processor/idempotent/FileIdempotentRepository.java
index e441977..eef5c6d 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/idempotent/FileIdempotentRepository.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/idempotent/FileIdempotentRepository.java
@@ -22,7 +22,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.api.management.ManagedAttribute;
@@ -289,22 +289,15 @@ public class FileIdempotentRepository extends ServiceSupport implements Idempote
             return false;
         }
 
-        Scanner scanner = null;
-        try {
-            scanner = new Scanner(fileStore);
-            scanner.useDelimiter(STORE_DELIMITER);
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine();
+        try (Scanner scanner = new Scanner(fileStore, null, STORE_DELIMITER)) {
+            while (scanner.hasNext()) {
+                String line = scanner.next();
                 if (line.equals(key)) {
                     return true;
                 }
             }
         } catch (IOException e) {
             throw ObjectHelper.wrapRuntimeCamelException(e);
-        } finally {
-            if (scanner != null) {
-                scanner.close();
-            }
         }
         return false;
     }
@@ -352,10 +345,9 @@ public class FileIdempotentRepository extends ServiceSupport implements Idempote
         boolean found = false;
         Scanner scanner = null;
         try {
-            scanner = new Scanner(fileStore);
-            scanner.useDelimiter(STORE_DELIMITER);
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine();
+            scanner = new Scanner(fileStore, null, STORE_DELIMITER);
+            while (scanner.hasNext()) {
+                String line = scanner.next();
                 if (key.equals(line)) {
                     found = true;
                 } else {
@@ -416,10 +408,9 @@ public class FileIdempotentRepository extends ServiceSupport implements Idempote
         Scanner scanner = null;
         int count = 0;
         try {
-            scanner = new Scanner(fileStore);
-            scanner.useDelimiter(STORE_DELIMITER);
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine();
+            scanner = new Scanner(fileStore, null, STORE_DELIMITER);
+            while (scanner.hasNext()) {
+                String line = scanner.next();
                 count++;
                 if (count > dropOldestFileStore) {
                     lines.add(line);
@@ -485,20 +476,13 @@ public class FileIdempotentRepository extends ServiceSupport implements Idempote
         LOG.trace("Loading to 1st level cache from idempotent filestore: {}", fileStore);
 
         cache.clear();
-        Scanner scanner = null;
-        try {
-            scanner = new Scanner(fileStore);
-            scanner.useDelimiter(STORE_DELIMITER);
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine();
+        try (Scanner scanner = new Scanner(fileStore, null, STORE_DELIMITER)) {
+            while (scanner.hasNext()) {
+                String line = scanner.next();
                 cache.put(line, line);
             }
         } catch (IOException e) {
             throw ObjectHelper.wrapRuntimeCamelException(e);
-        } finally {
-            if (scanner != null) {
-                scanner.close();
-            }
         }
 
         LOG.debug("Loaded {} to the 1st level cache from idempotent filestore: {}", cache.size(), fileStore);
diff --git a/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java b/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java
index 39c9a10..0ccfdd3 100644
--- a/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java
+++ b/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java
@@ -20,7 +20,7 @@ import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Iterator;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
@@ -160,7 +160,7 @@ public class TokenPairExpressionIterator extends ExpressionAdapter {
 
         void init() {
             // use end token as delimiter
-            this.scanner = new Scanner(in, charset).useDelimiter(scanEndToken);
+            this.scanner = new Scanner(in, charset, scanEndToken);
             // this iterator will do look ahead as we may have data
             // after the last end token, which the scanner would find
             // so we need to be one step ahead of the scanner
diff --git a/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java b/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
index 6e838fb..39664c9 100644
--- a/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
+++ b/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
@@ -20,7 +20,7 @@ import java.io.InputStream;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -122,7 +122,7 @@ public class TokenXMLPairExpressionIterator extends TokenPairExpressionIterator
         @Override
         void init() {
             // use scan end token as delimiter which supports attributes/namespaces
-            this.scanner = new Scanner(in, charset).useDelimiter(scanEndToken);
+            this.scanner = new Scanner(in, charset, scanEndToken);
             // this iterator will do look ahead as we may have data
             // after the last end token, which the scanner would find
             // so we need to be one step ahead of the scanner
diff --git a/camel-core/src/main/java/org/apache/camel/util/GroupIterator.java b/camel-core/src/main/java/org/apache/camel/util/GroupIterator.java
index e5c6ab2..b56c421 100644
--- a/camel-core/src/main/java/org/apache/camel/util/GroupIterator.java
+++ b/camel-core/src/main/java/org/apache/camel/util/GroupIterator.java
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Scanner;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
@@ -77,17 +76,7 @@ public final class GroupIterator implements Iterator<Object>, Closeable {
     @Override
     public void close() throws IOException {
         try {
-            if (it instanceof Scanner) {
-                // special for Scanner which implement the Closeable since JDK7 
-                Scanner scanner = (Scanner) it;
-                scanner.close();
-                IOException ioException = scanner.ioException();
-                if (ioException != null) {
-                    throw ioException;
-                }
-            } else if (it instanceof Closeable) {
-                IOHelper.closeWithException((Closeable) it);
-            }
+            IOHelper.closeIterator(it);
         } finally {
             // we are now closed
             closed = true;
diff --git a/camel-core/src/main/java/org/apache/camel/util/GroupTokenIterator.java b/camel-core/src/main/java/org/apache/camel/util/GroupTokenIterator.java
index 2f05116..0fa0a5c 100644
--- a/camel-core/src/main/java/org/apache/camel/util/GroupTokenIterator.java
+++ b/camel-core/src/main/java/org/apache/camel/util/GroupTokenIterator.java
@@ -21,7 +21,7 @@ import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Iterator;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.CamelContext;
@@ -102,17 +102,7 @@ public final class GroupTokenIterator implements Iterator<Object>, Closeable {
     @Override
     public void close() throws IOException {
         try {
-            if (it instanceof Scanner) {
-                // special for Scanner which implement the Closeable since JDK7 
-                Scanner scanner = (Scanner) it;
-                scanner.close();
-                IOException ioException = scanner.ioException();
-                if (ioException != null) {
-                    throw ioException;
-                }
-            } else if (it instanceof Closeable) {
-                IOHelper.closeWithException((Closeable) it);
-            }
+            IOHelper.closeIterator(it);
         } finally {
             // close the buffer as well
             bos.close();
diff --git a/camel-core/src/main/java/org/apache/camel/util/IOHelper.java b/camel-core/src/main/java/org/apache/camel/util/IOHelper.java
index 602c07b..e74cf44 100644
--- a/camel-core/src/main/java/org/apache/camel/util/IOHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IOHelper.java
@@ -417,6 +417,29 @@ public final class IOHelper {
         }
     }
 
+    public static void closeIterator(Object it) throws IOException {
+        if (it instanceof java.util.Scanner) {
+            // special for Scanner which implement the Closeable since JDK7
+            java.util.Scanner scanner = (java.util.Scanner) it;
+            scanner.close();
+            IOException ioException = scanner.ioException();
+            if (ioException != null) {
+                throw ioException;
+            }
+        } else if (it instanceof Scanner) {
+            // special for Scanner which implement the Closeable since JDK7
+            Scanner scanner = (Scanner) it;
+            scanner.close();
+            IOException ioException = scanner.ioException();
+            if (ioException != null) {
+                throw ioException;
+            }
+
+        } else if (it instanceof Closeable) {
+            IOHelper.closeWithException((Closeable) it);
+        }
+    }
+
     public static void validateCharset(String charset) throws UnsupportedCharsetException {
         if (charset != null) {
             if (Charset.isSupported(charset)) {
diff --git a/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java b/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
index ab98900..949a253 100644
--- a/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
@@ -18,7 +18,6 @@ package org.apache.camel.util;
 
 import java.io.Closeable;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
@@ -44,7 +43,6 @@ import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
-import java.util.Scanner;
 import java.util.concurrent.Callable;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -932,9 +930,6 @@ public final class ObjectHelper {
             // this code is optimized to only use a Scanner if needed, eg there is a delimiter
 
             if (delimiter != null && (pattern || s.contains(delimiter))) {
-                // use a scanner if it contains the delimiter or is a pattern
-                final Scanner scanner = new Scanner((String)value);
-
                 if (DEFAULT_DELIMITER.equals(delimiter)) {
                     // we use the default delimiter which is a comma, then cater for bean expressions with OGNL
                     // which may have balanced parentheses pairs as well.
@@ -948,7 +943,8 @@ public final class ObjectHelper {
                     // http://stackoverflow.com/questions/1516090/splitting-a-title-into-separate-parts
                     delimiter = ",(?!(?:[^\\(,]|[^\\)],[^\\)])+\\))";
                 }
-                scanner.useDelimiter(delimiter);
+                // use a scanner if it contains the delimiter or is a pattern
+                final Scanner scanner = new Scanner((String) value, delimiter);
 
                 return new Iterable<Object>() {
                     @Override
@@ -1938,9 +1934,10 @@ public final class ObjectHelper {
      *
      * @param exchange  the current exchange
      * @param value     the value, typically the message IN body
+     * @param delimiter the delimiter pattern to use
      * @return the scanner, is newer <tt>null</tt>
      */
-    public static Scanner getScanner(Exchange exchange, Object value) {
+    public static Scanner getScanner(Exchange exchange, Object value, String delimiter) {
         if (value instanceof WrappedFile) {
             WrappedFile<?> gf = (WrappedFile<?>) value;
             Object body = gf.getBody();
@@ -1949,41 +1946,33 @@ public final class ObjectHelper {
                 value = body;
             } else {
                 // generic file is just a wrapper for the real file so call again with the real file
-                return getScanner(exchange, gf.getFile());
+                return getScanner(exchange, gf.getFile(), delimiter);
             }
         }
 
-        String charset = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
-
-        Scanner scanner = null;
+        Scanner scanner;
         if (value instanceof Readable) {
-            scanner = new Scanner((Readable)value);
-        } else if (value instanceof InputStream) {
-            scanner = charset == null ? new Scanner((InputStream)value) : new Scanner((InputStream)value, charset);
-        } else if (value instanceof File) {
-            try {
-                scanner = charset == null ? new Scanner((File)value) : new Scanner((File)value, charset);
-            } catch (FileNotFoundException e) {
-                throw new RuntimeCamelException(e);
-            }
+            scanner = new Scanner((Readable) value, delimiter);
         } else if (value instanceof String) {
-            scanner = new Scanner((String)value);
-        } else if (value instanceof ReadableByteChannel) {
-            scanner = charset == null ? new Scanner((ReadableByteChannel)value) : new Scanner((ReadableByteChannel)value, charset);
-        }
-
-        if (scanner == null) {
-            // value is not a suitable type, try to convert value to a string
-            String text = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
-            if (text != null) {
-                scanner = new Scanner(text);
+            scanner = new Scanner((String) value, delimiter);
+        } else {
+            String charset = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
+            if (value instanceof File) {
+                try {
+                    scanner = new Scanner((File) value, charset, delimiter);
+                } catch (IOException e) {
+                    throw new RuntimeCamelException(e);
+                }
+            } else if (value instanceof InputStream) {
+                scanner = new Scanner((InputStream) value, charset, delimiter);
+            } else if (value instanceof ReadableByteChannel) {
+                scanner = new Scanner((ReadableByteChannel) value, charset, delimiter);
+            } else {
+                // value is not a suitable type, try to convert value to a string
+                String text = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
+                scanner = new Scanner(text, delimiter);
             }
         }
-
-        if (scanner == null) {
-            scanner = new Scanner("");
-        }
-
         return scanner;
     }
 
diff --git a/camel-core/src/main/java/org/apache/camel/util/Scanner.java b/camel-core/src/main/java/org/apache/camel/util/Scanner.java
new file mode 100644
index 0000000..a042c57
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/util/Scanner.java
@@ -0,0 +1,303 @@
+/**
+ * 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.util;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.InputMismatchException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class Scanner implements Iterator<String>, Closeable {
+
+    private static final Map<String, Pattern> CACHE = LRUCacheFactory.newLRUCache(7);
+
+    private static final String WHITESPACE_PATTERN = "\\s+";
+
+    private static final String FIND_ANY_PATTERN = "(?s).*";
+
+    private static final int BUFFER_SIZE = 1024;
+
+    private Readable source;
+    private Pattern delimPattern;
+    private Matcher matcher;
+    private CharBuffer buf;
+    private int position;
+    private boolean inputExhausted = false;
+    private boolean needInput = false;
+    private boolean skipped = false;
+    private int savedPosition = -1;
+    private boolean closed = false;
+    private IOException lastIOException;
+
+    public Scanner(InputStream source, String charsetName, String pattern) {
+        this(new InputStreamReader(Objects.requireNonNull(source, "source"), toDecoder(charsetName)), cachePattern(pattern));
+    }
+
+    public Scanner(File source, String charsetName, String pattern) throws FileNotFoundException {
+        this(new FileInputStream(Objects.requireNonNull(source, "source")).getChannel(), charsetName, pattern);
+    }
+
+    public Scanner(String source, String pattern) {
+        this(new StringReader(Objects.requireNonNull(source, "source")), cachePattern(pattern));
+    }
+
+    public Scanner(ReadableByteChannel source, String charsetName, String pattern) {
+        this(Channels.newReader(Objects.requireNonNull(source, "source"), toDecoder(charsetName), -1), cachePattern(pattern));
+    }
+
+    public Scanner(Readable source, String pattern) {
+        this(Objects.requireNonNull(source, "source"), cachePattern(pattern));
+    }
+
+    private Scanner(Readable source, Pattern pattern) {
+        this.source = source;
+        delimPattern = pattern != null ? pattern : cachePattern(WHITESPACE_PATTERN);
+        buf = CharBuffer.allocate(BUFFER_SIZE);
+        buf.limit(0);
+        matcher = delimPattern.matcher(buf);
+        matcher.useTransparentBounds(true);
+        matcher.useAnchoringBounds(false);
+    }
+
+    private static CharsetDecoder toDecoder(String charsetName) {
+        try {
+            Charset cs = charsetName != null ? Charset.forName(charsetName) : Charset.defaultCharset();
+            return cs.newDecoder();
+        } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    public boolean hasNext() {
+        checkClosed();
+        saveState();
+        while (!inputExhausted) {
+            if (hasTokenInBuffer()) {
+                revertState();
+                return true;
+            }
+            readMore();
+        }
+        boolean result = hasTokenInBuffer();
+        revertState();
+        return result;
+    }
+
+    public String next() {
+        checkClosed();
+        while (true) {
+            String token = getCompleteTokenInBuffer();
+            if (token != null) {
+                skipped = false;
+                return token;
+            }
+            if (needInput) {
+                readMore();
+            } else {
+                throwFor();
+            }
+        }
+    }
+
+    private void saveState() {
+        savedPosition = position;
+    }
+
+    private void revertState() {
+        position = savedPosition;
+        savedPosition = -1;
+        skipped = false;
+    }
+
+    private void readMore() {
+        if (buf.limit() == buf.capacity()) {
+            expandBuffer();
+        }
+        int p = buf.position();
+        buf.position(buf.limit());
+        buf.limit(buf.capacity());
+        int n;
+        try {
+            n = source.read(buf);
+        } catch (IOException ioe) {
+            lastIOException = ioe;
+            n = -1;
+        }
+        if (n == -1) {
+            inputExhausted = true;
+            needInput = false;
+        } else if (n > 0) {
+            needInput = false;
+        }
+        buf.limit(buf.position());
+        buf.position(p);
+    }
+
+    private void expandBuffer() {
+        int offset = savedPosition == -1 ? position : savedPosition;
+        buf.position(offset);
+        if (offset > 0) {
+            buf.compact();
+            translateSavedIndexes(offset);
+            position -= offset;
+            buf.flip();
+        } else {
+            int newSize = buf.capacity() * 2;
+            CharBuffer newBuf = CharBuffer.allocate(newSize);
+            newBuf.put(buf);
+            newBuf.flip();
+            translateSavedIndexes(offset);
+            position -= offset;
+            buf = newBuf;
+            matcher.reset(buf);
+        }
+    }
+
+    private void translateSavedIndexes(int offset) {
+        if (savedPosition != -1) {
+            savedPosition -= offset;
+        }
+    }
+
+    private void throwFor() {
+        skipped = false;
+        if ((inputExhausted) && (position == buf.limit())) {
+            throw new NoSuchElementException();
+        } else {
+            throw new InputMismatchException();
+        }
+    }
+
+    private boolean hasTokenInBuffer() {
+        matcher.usePattern(delimPattern);
+        matcher.region(position, buf.limit());
+        if (matcher.lookingAt()) {
+            position = matcher.end();
+        }
+        return position != buf.limit();
+    }
+
+    private String getCompleteTokenInBuffer() {
+        matcher.usePattern(delimPattern);
+        if (!skipped) {
+            matcher.region(position, buf.limit());
+            if (matcher.lookingAt()) {
+                if (matcher.hitEnd() && !inputExhausted) {
+                    needInput = true;
+                    return null;
+                }
+                skipped = true;
+                position = matcher.end();
+            }
+        }
+        if (position == buf.limit()) {
+            if (inputExhausted) {
+                return null;
+            }
+            needInput = true;
+            return null;
+        }
+        matcher.region(position, buf.limit());
+        boolean foundNextDelim = matcher.find();
+        if (foundNextDelim && (matcher.end() == position)) {
+            foundNextDelim = matcher.find();
+        }
+        if (foundNextDelim) {
+            if (matcher.requireEnd() && !inputExhausted) {
+                needInput = true;
+                return null;
+            }
+            int tokenEnd = matcher.start();
+            matcher.usePattern(cachePattern(FIND_ANY_PATTERN));
+            matcher.region(position, tokenEnd);
+            if (matcher.matches()) {
+                String s = matcher.group();
+                position = matcher.end();
+                return s;
+            } else {
+                return null;
+            }
+        }
+        if (inputExhausted) {
+            matcher.usePattern(cachePattern(FIND_ANY_PATTERN));
+            matcher.region(position, buf.limit());
+            if (matcher.matches()) {
+                String s = matcher.group();
+                position = matcher.end();
+                return s;
+            }
+            return null;
+        }
+        needInput = true;
+        return null;
+    }
+
+    private void checkClosed() {
+        if (closed) {
+            throw new IllegalStateException();
+        }
+    }
+
+    public void close() {
+        if (!closed) {
+            if (source instanceof Closeable) {
+                try {
+                    ((Closeable) source).close();
+                } catch (IOException e) {
+                    lastIOException = e;
+                }
+            }
+            closed = true;
+        }
+    }
+
+    public IOException ioException() {
+        return lastIOException;
+    }
+
+    private static Pattern cachePattern(String pattern) {
+        if (pattern == null) {
+            return null;
+        }
+        return CACHE.computeIfAbsent(pattern, new Function<String, Pattern>() {
+            @Override
+            public Pattern apply(String s) {
+                return Pattern.compile(s);
+            }
+        });
+    }
+
+}
diff --git a/camel-core/src/main/java/org/apache/camel/util/SkipIterator.java b/camel-core/src/main/java/org/apache/camel/util/SkipIterator.java
index ee43064..9c9b622 100644
--- a/camel-core/src/main/java/org/apache/camel/util/SkipIterator.java
+++ b/camel-core/src/main/java/org/apache/camel/util/SkipIterator.java
@@ -19,7 +19,7 @@ package org.apache.camel.util;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.Iterator;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.CamelContext;
@@ -58,17 +58,7 @@ public final class SkipIterator implements Iterator<Object>, Closeable {
     @Override
     public void close() throws IOException {
         try {
-            if (it instanceof Scanner) {
-                // special for Scanner which implement the Closeable since JDK7 
-                Scanner scanner = (Scanner) it;
-                scanner.close();
-                IOException ioException = scanner.ioException();
-                if (ioException != null) {
-                    throw ioException;
-                }
-            } else if (it instanceof Closeable) {
-                IOHelper.closeWithException((Closeable) it);
-            }
+            IOHelper.closeIterator(it);
         } finally {
             // we are now closed
             closed = true;
diff --git a/camel-core/src/test/java/org/apache/camel/util/GroupTokenIteratorTest.java b/camel-core/src/test/java/org/apache/camel/util/GroupTokenIteratorTest.java
index 84eb610..dfff48c 100644
--- a/camel-core/src/test/java/org/apache/camel/util/GroupTokenIteratorTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/GroupTokenIteratorTest.java
@@ -19,7 +19,7 @@ package org.apache.camel.util;
 import java.io.ByteArrayInputStream;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
-import java.util.Scanner;
+import org.apache.camel.util.Scanner;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
@@ -52,8 +52,7 @@ public class GroupTokenIteratorTest extends TestSupport {
 
     public void testGroupIterator() throws Exception {
         String s = "ABC\nDEF\nGHI\nJKL\nMNO\nPQR\nSTU\nVW";
-        Scanner scanner = new Scanner(s);
-        scanner.useDelimiter("\n");
+        Scanner scanner = new Scanner(s, "\n");
 
         GroupTokenIterator gi = new GroupTokenIterator(exchange, scanner, "\n", 3, false);
 
@@ -68,8 +67,7 @@ public class GroupTokenIteratorTest extends TestSupport {
 
     public void testGroupIteratorSkipFirst() throws Exception {
         String s = "##comment\nABC\nDEF\nGHI\nJKL\nMNO\nPQR\nSTU\nVW";
-        Scanner scanner = new Scanner(s);
-        scanner.useDelimiter("\n");
+        Scanner scanner = new Scanner(s, "\n");
 
         GroupTokenIterator gi = new GroupTokenIterator(exchange, scanner, "\n", 3, true);
 
@@ -92,8 +90,7 @@ public class GroupTokenIteratorTest extends TestSupport {
 
         ByteArrayInputStream in = new ByteArrayInputStream(buf);
 
-        Scanner scanner = new Scanner(in, StandardCharsets.UTF_8.displayName());
-        scanner.useDelimiter("\n");
+        Scanner scanner = new Scanner(in, StandardCharsets.UTF_8.displayName(), "\n");
 
         exchange.setProperty(Exchange.CHARSET_NAME, StandardCharsets.UTF_8.displayName());
         GroupTokenIterator gi = new GroupTokenIterator(exchange, scanner, "\n", 1, false);


[camel] 04/05: [CAMEL-12688] Improve introspection performances

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

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7af620666722660db19f98ce18b7685b57be5c9a
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon Jun 25 15:22:58 2018 +0200

    [CAMEL-12688] Improve introspection performances
---
 .../org/apache/camel/util/IntrospectionSupport.java | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
index 5445816..008c6e1 100644
--- a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
@@ -308,6 +308,8 @@ public final class IntrospectionSupport {
         // especially about getter/setters
         List<MethodInfo> found = new ArrayList<>();
         Method[] methods = clazz.getMethods();
+        Map<String, MethodInfo> getters = new HashMap<>(methods.length);
+        Map<String, MethodInfo> setters = new HashMap<>(methods.length);
         for (Method method : methods) {
             if (EXCLUDED_METHODS.contains(method)) {
                 continue;
@@ -319,14 +321,15 @@ public final class IntrospectionSupport {
                 cache.isGetter = true;
                 cache.isSetter = false;
                 cache.getterOrSetterShorthandName = getGetterShorthandName(method);
+                getters.put(cache.getterOrSetterShorthandName, cache);
             } else if (isSetter(method)) {
                 cache.isGetter = false;
                 cache.isSetter = true;
                 cache.getterOrSetterShorthandName = getSetterShorthandName(method);
+                setters.put(cache.getterOrSetterShorthandName, cache);
             } else {
                 cache.isGetter = false;
                 cache.isSetter = false;
-                cache.hasGetterAndSetter = false;
             }
             found.add(cache);
         }
@@ -336,21 +339,9 @@ public final class IntrospectionSupport {
         for (MethodInfo info : found) {
             info.hasGetterAndSetter = false;
             if (info.isGetter) {
-                // loop and find the matching setter
-                for (MethodInfo info2 : found) {
-                    if (info2.isSetter && info.getterOrSetterShorthandName.equals(info2.getterOrSetterShorthandName)) {
-                        info.hasGetterAndSetter = true;
-                        break;
-                    }
-                }
+                info.hasGetterAndSetter = setters.containsKey(info.getterOrSetterShorthandName);
             } else if (info.isSetter) {
-                // loop and find the matching getter
-                for (MethodInfo info2 : found) {
-                    if (info2.isGetter && info.getterOrSetterShorthandName.equals(info2.getterOrSetterShorthandName)) {
-                        info.hasGetterAndSetter = true;
-                        break;
-                    }
-                }
+                info.hasGetterAndSetter = getters.containsKey(info.getterOrSetterShorthandName);
             }
         }