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

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

commit b41df862371e1d42049ac1b3c89de29412a1176a
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon May 13 10:07:42 2019 +0200

    CAMEL-13503: Camel main - Allow to configure global and common options ala 
camel-spring-boot have.
---
 .../camel/main/MainConfigurationProperties.java    |   8 +-
 .../java/org/apache/camel/main/MainSupport.java    | 354 ++++++++++++++++++---
 .../src/main/resources/application.properties      |   7 +-
 3 files changed, 326 insertions(+), 43 deletions(-)

diff --git 
a/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
 
b/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 9bcaa89..2ce8ac3 100644
--- 
a/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ 
b/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -198,7 +198,7 @@ public class MainConfigurationProperties {
 
     /**
      * To specify for how long time in seconds to keep running the JVM before 
automatic terminating the JVM.
-     * You can use this to run Spring Boot for a short while.
+     * You can use this to run Camel for a short while.
      */
     public void setDurationMaxSeconds(int durationMaxSeconds) {
         this.durationMaxSeconds = durationMaxSeconds;
@@ -210,7 +210,7 @@ public class MainConfigurationProperties {
 
     /**
      * To specify for how long time in seconds Camel can be idle before 
automatic terminating the JVM.
-     * You can use this to run Spring Boot for a short while.
+     * You can use this to run Camel for a short while.
      */
     public void setDurationMaxIdleSeconds(int durationMaxIdleSeconds) {
         this.durationMaxIdleSeconds = durationMaxIdleSeconds;
@@ -222,7 +222,7 @@ public class MainConfigurationProperties {
 
     /**
      * To specify how many messages to process by Camel before automatic 
terminating the JVM.
-     * You can use this to run Spring Boot for a short while.
+     * You can use this to run Camel for a short while.
      */
     public void setDurationMaxMessages(int durationMaxMessages) {
         this.durationMaxMessages = durationMaxMessages;
@@ -573,4 +573,6 @@ public class MainConfigurationProperties {
     public void setThreadNamePattern(String threadNamePattern) {
         this.threadNamePattern = threadNamePattern;
     }
+
+    
 }
diff --git 
a/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java 
b/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java
index b974f36..44aa577 100644
--- a/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -31,26 +32,57 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.ProducerTemplate;
+import org.apache.camel.TypeConverters;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.cloud.ServiceRegistry;
+import org.apache.camel.cluster.CamelClusterService;
+import org.apache.camel.health.HealthCheckRegistry;
+import org.apache.camel.health.HealthCheckRepository;
+import org.apache.camel.health.HealthCheckService;
+import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.FileWatcherReloadStrategy;
 import org.apache.camel.model.Model;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.processor.interceptor.BacklogTracer;
+import org.apache.camel.processor.interceptor.HandleFault;
+import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.EndpointStrategy;
+import org.apache.camel.spi.EventFactory;
 import org.apache.camel.spi.EventNotifier;
+import org.apache.camel.spi.ExecutorServiceManager;
+import org.apache.camel.spi.InflightRepository;
+import org.apache.camel.spi.InterceptStrategy;
 import org.apache.camel.spi.Language;
+import org.apache.camel.spi.LifecycleStrategy;
+import org.apache.camel.spi.LogListener;
+import org.apache.camel.spi.ManagementObjectNameStrategy;
+import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.spi.PropertiesComponent;
+import org.apache.camel.spi.Registry;
 import org.apache.camel.spi.ReloadStrategy;
+import org.apache.camel.spi.RouteController;
+import org.apache.camel.spi.RoutePolicyFactory;
+import org.apache.camel.spi.RuntimeEndpointRegistry;
+import org.apache.camel.spi.ShutdownStrategy;
+import org.apache.camel.spi.StreamCachingStrategy;
+import org.apache.camel.spi.ThreadPoolProfile;
+import org.apache.camel.spi.UnitOfWorkFactory;
+import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.support.DefaultExchange;
 import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.support.IntrospectionSupport;
 import org.apache.camel.support.LifecycleStrategySupport;
+import org.apache.camel.support.jsse.GlobalSSLContextParametersSupplier;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.ObjectHelper;
@@ -74,17 +106,14 @@ public abstract class MainSupport extends ServiceSupport {
     protected final AtomicBoolean completed = new AtomicBoolean(false);
     protected final AtomicInteger exitCode = new 
AtomicInteger(UNINITIALIZED_EXIT_CODE);
 
+    // TODO: Fluent builder on Main configuration properties
+    // TODO: Make it possible to configure MainConfigurationProperties from 
application.properties via camel.main.xxx
     // TODO: Move these to mainConfigurationProperties (delegate)
     protected long duration = -1;
-    protected long durationIdle = -1;
-    protected int durationMaxMessages;
-    protected TimeUnit timeUnit = TimeUnit.SECONDS;
-    protected boolean trace;
     protected String fileWatchDirectory;
     protected boolean fileWatchDirectoryRecursively;
 
     protected CamelContext camelContext;
-    // TODO: Make it possible to configure MainConfigurationProperties from 
application.properties via camel.main.xxx
     protected final MainConfigurationProperties mainConfigurationProperties = 
new MainConfigurationProperties();
     protected List<RouteBuilder> routeBuilders = new ArrayList<>();
     protected String routeBuilderClasses;
@@ -386,8 +415,8 @@ public abstract class MainSupport extends ServiceSupport {
         this.duration = duration;
     }
 
-    public long getDurationIdle() {
-        return durationIdle;
+    public int getDurationIdle() {
+        return mainConfigurationProperties.getDurationMaxIdleSeconds();
     }
 
     /**
@@ -396,12 +425,12 @@ public abstract class MainSupport extends ServiceSupport {
      * then the application should be terminated.
      * Defaults to -1. Any value <= 0 will run forever.
      */
-    public void setDurationIdle(long durationIdle) {
-        this.durationIdle = durationIdle;
+    public void setDurationIdle(int durationIdle) {
+        mainConfigurationProperties.setDurationMaxIdleSeconds(durationIdle);
     }
 
     public int getDurationMaxMessages() {
-        return durationMaxMessages;
+        return mainConfigurationProperties.getDurationMaxMessages();
     }
 
     /**
@@ -409,18 +438,7 @@ public abstract class MainSupport extends ServiceSupport {
      * should be terminated. Defaults to -1. Any value <= 0 will run forever.
      */
     public void setDurationMaxMessages(int durationMaxMessages) {
-        this.durationMaxMessages = durationMaxMessages;
-    }
-
-    public TimeUnit getTimeUnit() {
-        return timeUnit;
-    }
-
-    /**
-     * Sets the time unit duration (seconds by default).
-     */
-    public void setTimeUnit(TimeUnit timeUnit) {
-        this.timeUnit = timeUnit;
+        
mainConfigurationProperties.setDurationMaxMessages(durationMaxMessages);
     }
 
     /**
@@ -578,11 +596,11 @@ public abstract class MainSupport extends ServiceSupport {
     }
 
     public boolean isTrace() {
-        return trace;
+        return mainConfigurationProperties.isTracing();
     }
 
     public void enableTrace() {
-        this.trace = true;
+        mainConfigurationProperties.setTracing(true);
     }
 
     protected void doStop() throws Exception {
@@ -597,19 +615,17 @@ public abstract class MainSupport extends ServiceSupport {
         while (!completed.get()) {
             try {
                 if (duration > 0) {
-                    TimeUnit unit = getTimeUnit();
-                    LOG.info("Waiting for: {} {}", duration, unit);
-                    latch.await(duration, unit);
+                    LOG.info("Waiting for: {} seconds", duration);
+                    latch.await(duration, TimeUnit.SECONDS);
                     exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, 
durationHitExitCode);
                     completed.set(true);
-                } else if (durationIdle > 0) {
-                    TimeUnit unit = getTimeUnit();
-                    LOG.info("Waiting to be idle for: {} {}", duration, unit);
+                } else if 
(mainConfigurationProperties.getDurationMaxIdleSeconds() > 0) {
+                    LOG.info("Waiting to be idle for: {} seconds", 
mainConfigurationProperties.getDurationMaxIdleSeconds());
                     exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, 
durationHitExitCode);
                     latch.await();
                     completed.set(true);
-                } else if (durationMaxMessages > 0) {
-                    LOG.info("Waiting until: {} messages has been processed", 
durationMaxMessages);
+                } else if 
(mainConfigurationProperties.getDurationMaxMessages() > 0) {
+                    LOG.info("Waiting until: {} messages has been processed", 
mainConfigurationProperties.getDurationMaxMessages());
                     exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, 
durationHitExitCode);
                     latch.await();
                     completed.set(true);
@@ -760,9 +776,6 @@ public abstract class MainSupport extends ServiceSupport {
             }
             LOG.info("Using optional properties from 
classpath:application.properties");
         }
-        if (trace) {
-            camelContext.setTracing(true);
-        }
         if (fileWatchDirectory != null) {
             ReloadStrategy reload = new 
FileWatcherReloadStrategy(fileWatchDirectory, fileWatchDirectoryRecursively);
             camelContext.setReloadStrategy(reload);
@@ -788,11 +801,10 @@ public abstract class MainSupport extends ServiceSupport {
             }
         }
 
-        if (durationMaxMessages > 0 || durationIdle > 0) {
-            // convert to seconds as that is what event notifier uses
-            long seconds = timeUnit.toSeconds(durationIdle);
+        if (mainConfigurationProperties.getDurationMaxMessages() > 0 || 
mainConfigurationProperties.getDurationMaxIdleSeconds() > 0) {
             // register lifecycle so we can trigger to shutdown the JVM when 
maximum number of messages has been processed
-            EventNotifier notifier = new 
MainDurationEventNotifier(camelContext, durationMaxMessages, seconds, 
completed, latch, true);
+            EventNotifier notifier = new 
MainDurationEventNotifier(camelContext, 
mainConfigurationProperties.getDurationMaxMessages(),
+                    mainConfigurationProperties.getDurationMaxIdleSeconds(), 
completed, latch, true);
             // register our event notifier
             ServiceHelper.startService(notifier);
             camelContext.getManagementStrategy().addEventNotifier(notifier);
@@ -801,8 +813,12 @@ public abstract class MainSupport extends ServiceSupport {
         // need to eager allow to auto configure properties component
         if (autoConfigurationEnabled) {
             autoConfigurationPropertiesComponent(camelContext);
+            autoConfigurationMainConfiguration(camelContext, 
mainConfigurationProperties);
         }
 
+        // configure from main configuration properties
+        doConfigureCamelContextFromMainConfiguration(camelContext, 
mainConfigurationProperties);
+
         // try to load configuration classes
         loadConfigurations(camelContext);
 
@@ -826,6 +842,244 @@ public abstract class MainSupport extends ServiceSupport {
         }
     }
 
+    /**
+     * Configures CamelContext from the {@link MainConfigurationProperties} 
properties.
+     */
+    protected void doConfigureCamelContextFromMainConfiguration(CamelContext 
camelContext, MainConfigurationProperties config) throws Exception {
+        if (!config.isJmxEnabled()) {
+            camelContext.disableJMX();
+        }
+
+        if (config.getName() != null) {
+            ((DefaultCamelContext) camelContext).setName(config.getName());
+        }
+
+        if (config.getShutdownTimeout() > 0) {
+            
camelContext.getShutdownStrategy().setTimeout(config.getShutdownTimeout());
+        }
+        
camelContext.getShutdownStrategy().setSuppressLoggingOnTimeout(config.isShutdownSuppressLoggingOnTimeout());
+        
camelContext.getShutdownStrategy().setShutdownNowOnTimeout(config.isShutdownNowOnTimeout());
+        
camelContext.getShutdownStrategy().setShutdownRoutesInReverseOrder(config.isShutdownRoutesInReverseOrder());
+        
camelContext.getShutdownStrategy().setLogInflightExchangesOnTimeout(config.isShutdownLogInflightExchangesOnTimeout());
+
+        if (config.getLogDebugMaxChars() != 0) {
+            
camelContext.getGlobalOptions().put(Exchange.LOG_DEBUG_BODY_MAX_CHARS, "" + 
config.getLogDebugMaxChars());
+        }
+
+        // stream caching
+        camelContext.setStreamCaching(config.isStreamCachingEnabled());
+        
camelContext.getStreamCachingStrategy().setAnySpoolRules(config.isStreamCachingAnySpoolRules());
+        
camelContext.getStreamCachingStrategy().setBufferSize(config.getStreamCachingBufferSize());
+        
camelContext.getStreamCachingStrategy().setRemoveSpoolDirectoryWhenStopping(config.isStreamCachingRemoveSpoolDirectoryWhenStopping());
+        
camelContext.getStreamCachingStrategy().setSpoolChiper(config.getStreamCachingSpoolChiper());
+        if (config.getStreamCachingSpoolDirectory() != null) {
+            
camelContext.getStreamCachingStrategy().setSpoolDirectory(config.getStreamCachingSpoolDirectory());
+        }
+        if (config.getStreamCachingSpoolThreshold() != 0) {
+            
camelContext.getStreamCachingStrategy().setSpoolThreshold(config.getStreamCachingSpoolThreshold());
+        }
+        if (config.getStreamCachingSpoolUsedHeapMemoryLimit() != null) {
+            StreamCachingStrategy.SpoolUsedHeapMemoryLimit limit;
+            if 
("Committed".equalsIgnoreCase(config.getStreamCachingSpoolUsedHeapMemoryLimit()))
 {
+                limit = 
StreamCachingStrategy.SpoolUsedHeapMemoryLimit.Committed;
+            } else if 
("Max".equalsIgnoreCase(config.getStreamCachingSpoolUsedHeapMemoryLimit())) {
+                limit = StreamCachingStrategy.SpoolUsedHeapMemoryLimit.Max;
+            } else {
+                throw new IllegalArgumentException("Invalid option " + 
config.getStreamCachingSpoolUsedHeapMemoryLimit() + " must either be Committed 
or Max");
+            }
+            
camelContext.getStreamCachingStrategy().setSpoolUsedHeapMemoryLimit(limit);
+        }
+        if (config.getStreamCachingSpoolUsedHeapMemoryThreshold() != 0) {
+            
camelContext.getStreamCachingStrategy().setSpoolUsedHeapMemoryThreshold(config.getStreamCachingSpoolUsedHeapMemoryThreshold());
+        }
+
+        camelContext.setMessageHistory(config.isMessageHistory());
+        camelContext.setLogMask(config.isLogMask());
+        
camelContext.setLogExhaustedMessageBody(config.isLogExhaustedMessageBody());
+        camelContext.setHandleFault(config.isHandleFault());
+        camelContext.setAutoStartup(config.isAutoStartup());
+        
camelContext.setAllowUseOriginalMessage(config.isAllowUseOriginalMessage());
+        camelContext.setUseBreadcrumb(config.isUseBreadcrumb());
+        camelContext.setUseDataType(config.isUseDataType());
+        camelContext.setUseMDCLogging(config.isUseMdcLogging());
+
+        if (camelContext.getManagementStrategy().getManagementAgent() != null) 
{
+            
camelContext.getManagementStrategy().getManagementAgent().setEndpointRuntimeStatisticsEnabled(config.isEndpointRuntimeStatisticsEnabled());
+            
camelContext.getManagementStrategy().getManagementAgent().setStatisticsLevel(config.getJmxManagementStatisticsLevel());
+            
camelContext.getManagementStrategy().getManagementAgent().setManagementNamePattern(config.getJmxManagementNamePattern());
+            
camelContext.getManagementStrategy().getManagementAgent().setCreateConnector(config.isJmxCreateConnector());
+        }
+
+        // tracing
+        camelContext.setTracing(config.isTracing());
+
+        if (config.getThreadNamePattern() != null) {
+            
camelContext.getExecutorServiceManager().setThreadNamePattern(config.getThreadNamePattern());
+        }
+
+        // additional advanced configuration which is not configured using 
CamelConfigurationProperties
+        afterPropertiesSet(camelContext.getRegistry(), camelContext);
+    }
+
+    /**
+     * Performs additional configuration to lookup beans of Camel types to 
configure
+     * advanced configurations.
+     * <p/>
+     * Similar code in camel-core-xml module in class 
org.apache.camel.core.xml.AbstractCamelContextFactoryBean
+     * or in camel-spring-boot module in class 
org.apache.camel.spring.boot.CamelAutoConfiguration.
+     */
+    static void afterPropertiesSet(Registry registry, CamelContext 
camelContext) throws Exception {
+        final ManagementStrategy managementStrategy = 
camelContext.getManagementStrategy();
+
+        registerPropertyForBeanType(registry, BacklogTracer.class, bt -> 
camelContext.setExtension(BacklogTracer.class, bt));
+        registerPropertyForBeanType(registry, HandleFault.class, 
camelContext::addInterceptStrategy);
+        registerPropertyForBeanType(registry, InflightRepository.class, 
camelContext::setInflightRepository);
+        registerPropertyForBeanType(registry, 
AsyncProcessorAwaitManager.class, camelContext::setAsyncProcessorAwaitManager);
+        registerPropertyForBeanType(registry, ManagementStrategy.class, 
camelContext::setManagementStrategy);
+        registerPropertyForBeanType(registry, 
ManagementObjectNameStrategy.class, 
managementStrategy::setManagementObjectNameStrategy);
+        registerPropertyForBeanType(registry, EventFactory.class, 
managementStrategy::setEventFactory);
+        registerPropertyForBeanType(registry, UnitOfWorkFactory.class, 
camelContext::setUnitOfWorkFactory);
+        registerPropertyForBeanType(registry, RuntimeEndpointRegistry.class, 
camelContext::setRuntimeEndpointRegistry);
+
+        registerPropertiesForBeanTypes(registry, TypeConverters.class, 
camelContext.getTypeConverterRegistry()::addTypeConverters);
+
+        final Predicate<EventNotifier> containsEventNotifier = 
managementStrategy.getEventNotifiers()::contains;
+        registerPropertiesForBeanTypesWithCondition(registry, 
EventNotifier.class, containsEventNotifier.negate(), 
managementStrategy::addEventNotifier);
+
+        registerPropertiesForBeanTypes(registry, EndpointStrategy.class, 
camelContext::addRegisterEndpointCallback);
+
+        registerPropertyForBeanType(registry, ShutdownStrategy.class, 
camelContext::setShutdownStrategy);
+
+        final Predicate<InterceptStrategy> containsInterceptStrategy = 
camelContext.getInterceptStrategies()::contains;
+        registerPropertiesForBeanTypesWithCondition(registry, 
InterceptStrategy.class, containsInterceptStrategy.negate(), 
camelContext::addInterceptStrategy);
+
+        final Predicate<LifecycleStrategy> containsLifecycleStrategy = 
camelContext.getLifecycleStrategies()::contains;
+        registerPropertiesForBeanTypesWithCondition(registry, 
LifecycleStrategy.class, containsLifecycleStrategy.negate(), 
camelContext::addLifecycleStrategy);
+
+        registerPropertiesForBeanTypes(registry, CamelClusterService.class, 
addServiceToContext(camelContext));
+
+        // service registry
+        Map<String, ServiceRegistry> serviceRegistries = 
registry.findByTypeWithName(ServiceRegistry.class);
+        if (serviceRegistries != null && !serviceRegistries.isEmpty()) {
+            for (Map.Entry<String, ServiceRegistry> entry : 
serviceRegistries.entrySet()) {
+                ServiceRegistry service = entry.getValue();
+
+                if (service.getId() == null) {
+                    
service.setId(camelContext.getUuidGenerator().generateUuid());
+                }
+
+                LOG.info("Using ServiceRegistry with id: {} and 
implementation: {}", service.getId(), service);
+                camelContext.addService(service);
+            }
+        }
+
+        registerPropertiesForBeanTypes(registry, RoutePolicyFactory.class, 
camelContext::addRoutePolicyFactory);
+
+        // add SSL context parameters
+        GlobalSSLContextParametersSupplier sslContextParametersSupplier = 
getSingleBeanOfType(registry, GlobalSSLContextParametersSupplier.class);
+        if (sslContextParametersSupplier != null) {
+            
camelContext.setSSLContextParameters(sslContextParametersSupplier.get());
+        }
+        // Health check registry
+        HealthCheckRegistry healthCheckRegistry = 
getSingleBeanOfType(registry, HealthCheckRegistry.class);
+        if (healthCheckRegistry != null) {
+            healthCheckRegistry.setCamelContext(camelContext);
+            LOG.info("Using HealthCheckRegistry: {}", healthCheckRegistry);
+            camelContext.setExtension(HealthCheckRegistry.class, 
healthCheckRegistry);
+        } else {
+            healthCheckRegistry = HealthCheckRegistry.get(camelContext);
+            healthCheckRegistry.setCamelContext(camelContext);
+        }
+
+        registerPropertiesForBeanTypes(registry, HealthCheckRepository.class, 
healthCheckRegistry::addRepository);
+
+        registerPropertyForBeanType(registry, HealthCheckService.class, 
addServiceToContext(camelContext));
+        registerPropertyForBeanType(registry, RouteController.class, 
camelContext::setRouteController);
+        registerPropertyForBeanType(registry, UuidGenerator.class, 
camelContext::setUuidGenerator);
+
+        final Predicate<LogListener> containsLogListener = 
camelContext.getLogListeners()::contains;
+        registerPropertiesForBeanTypesWithCondition(registry, 
LogListener.class, containsLogListener.negate(), camelContext::addLogListener);
+
+        registerPropertyForBeanType(registry, ExecutorServiceManager.class, 
camelContext::setExecutorServiceManager);
+
+        // set the default thread pool profile if defined
+        initThreadPoolProfiles(registry, camelContext);
+    }
+
+    private static void initThreadPoolProfiles(Registry registry, CamelContext 
camelContext) {
+        Set<String> defaultIds = new HashSet<>();
+
+        // lookup and use custom profiles from the registry
+        Map<String, ThreadPoolProfile> profiles = 
registry.findByTypeWithName(ThreadPoolProfile.class);
+        if (profiles != null && !profiles.isEmpty()) {
+            for (Map.Entry<String, ThreadPoolProfile> entry : 
profiles.entrySet()) {
+                ThreadPoolProfile profile = entry.getValue();
+                // do not add if already added, for instance a tracer that is 
also an InterceptStrategy class
+                if (profile.isDefaultProfile()) {
+                    LOG.info("Using custom default ThreadPoolProfile with id: 
{} and implementation: {}", entry.getKey(), profile);
+                    
camelContext.getExecutorServiceManager().setDefaultThreadPoolProfile(profile);
+                    defaultIds.add(entry.getKey());
+                } else {
+                    
camelContext.getExecutorServiceManager().registerThreadPoolProfile(profile);
+                }
+            }
+        }
+
+        // validate at most one is defined
+        if (defaultIds.size() > 1) {
+            throw new IllegalArgumentException("Only exactly one default 
ThreadPoolProfile is allowed, was " + defaultIds.size() + " ids: " + 
defaultIds);
+        }
+    }
+
+    private static <T> void registerPropertyForBeanType(final Registry 
registry, final Class<T> beanType, final Consumer<T> propertySetter) {
+        T propertyBean = getSingleBeanOfType(registry, beanType);
+        if (propertyBean == null) {
+            return;
+        }
+
+        LOG.info("Using custom {}: {}", beanType.getSimpleName(), 
propertyBean);
+        propertySetter.accept(propertyBean);
+    }
+
+    private static <T> T getSingleBeanOfType(Registry registry, Class<T> type) 
{
+        Map<String, T> beans = registry.findByTypeWithName(type);
+        if (beans.size() == 1) {
+            return beans.values().iterator().next();
+        } else {
+            return null;
+        }
+    }
+
+    private static <T> void registerPropertiesForBeanTypes(final Registry 
registry, final Class<T> beanType, final Consumer<T> propertySetter) {
+        registerPropertiesForBeanTypesWithCondition(registry, beanType, b -> 
true, propertySetter);
+    }
+
+    private static <T> void registerPropertiesForBeanTypesWithCondition(final 
Registry registry, final Class<T> beanType, final Predicate<T> condition,
+                                                                        final 
Consumer<T> propertySetter) {
+        final Map<String, T> beans = registry.findByTypeWithName(beanType);
+        if (!ObjectHelper.isNotEmpty(beans)) {
+            return;
+        }
+
+        final String simpleName = beanType.getSimpleName();
+        beans.forEach((name, bean) -> {
+            if (condition.test(bean)) {
+                LOG.info("Adding custom {} with id: {} and implementation: 
{}", simpleName, name, bean);
+                propertySetter.accept(bean);
+            }
+        });
+    }
+
+    private static <T> Consumer<T> addServiceToContext(final CamelContext 
camelContext) {
+        return service -> {
+            try {
+                camelContext.addService(service);
+            } catch (Exception e) {
+                throw new RuntimeException("Unable to add service to Camel 
context", e);
+            }
+        };
+    }
+
     protected void autoConfigurationPropertiesComponent(CamelContext 
camelContext) throws Exception {
         // load properties
         Properties prop = 
camelContext.getPropertiesComponent().loadProperties();
@@ -856,6 +1110,28 @@ public abstract class MainSupport extends ServiceSupport {
         }
     }
 
+    protected void autoConfigurationMainConfiguration(CamelContext 
camelContext, MainConfigurationProperties config) throws Exception {
+        // load properties
+        Properties prop = 
camelContext.getPropertiesComponent().loadProperties();
+
+        Map<String, Object> properties = new LinkedHashMap<>();
+
+        for (String key : prop.stringPropertyNames()) {
+            if (key.startsWith("camel.main.")) {
+                // grab the value
+                String value = prop.getProperty(key);
+                String option = key.substring(11);
+                properties.put(option, value);
+            }
+        }
+
+        if (!properties.isEmpty()) {
+            LOG.info("Auto configuring main from loaded properties: {}", 
properties.size());
+        }
+
+        setCamelProperties(camelContext, config, properties, true);
+    }
+
     protected void autoConfigurationFromProperties(CamelContext camelContext) 
throws Exception {
         // load properties
         Properties prop = 
camelContext.getPropertiesComponent().loadProperties();
diff --git 
a/examples/camel-example-main/src/main/resources/application.properties 
b/examples/camel-example-main/src/main/resources/application.properties
index 859f3cb..f07d91c 100644
--- a/examples/camel-example-main/src/main/resources/application.properties
+++ b/examples/camel-example-main/src/main/resources/application.properties
@@ -15,12 +15,17 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
+# to configure camel main
+# here you can configure options on camel main (see 
MainConfigurationProperties class)
+camel.main.name = MyCoolCamel
+camel.main.jmx-enabled = false
+
 # to configure the camel quartz component
 # here we can configure the options on the component level (and we can use 
dash-naming-style)
 camel.component.quartz2.start-delayed-seconds = 3
 
 # you can configure whether OS environment should override (=2 which is 
default) or as fallback (=1)
-camel.component.properties.environment-variable-mode=1
+### camel.component.properties.environment-variable-mode=1
 
 # properties used in the route
 myCron = 0/2 * * * * ?

Reply via email to