This is an automated email from the ASF dual-hosted git repository. orpiske pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit e0376969239d08d9cf9c14022f5393a0766fcbc4 Author: Otavio Rodolfo Piske <[email protected]> AuthorDate: Thu Mar 23 11:45:05 2023 +0100 CAMEL-15105: created a plugin manager to manage extensions to the context --- .../org/apache/camel/ExtendedCamelContext.java | 23 ++++++++ .../java/org/apache/camel/spi/PluginManager.java | 36 +++++++++++++ .../camel/impl/engine/AbstractCamelContext.java | 37 +++---------- .../impl/engine/DefaultCamelContextExtension.java | 27 ++++++++++ .../impl/engine/DefaultContextPluginManager.java | 63 ++++++++++++++++++++++ .../impl/lw/LightweightCamelContextExtension.java | 16 ++++++ 6 files changed, 172 insertions(+), 30 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java index 6566b09778a..641a0bac7fc 100644 --- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java +++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java @@ -61,6 +61,7 @@ import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.PeriodTaskResolver; import org.apache.camel.spi.PeriodTaskScheduler; +import org.apache.camel.spi.PluginManager; import org.apache.camel.spi.ProcessorExchangeFactory; import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.ReactiveExecutor; @@ -910,4 +911,26 @@ public interface ExtendedCamelContext { */ void setPeriodTaskResolver(PeriodTaskResolver periodTaskResolver); + /** + * Gets access to the internal plugin manager + * @return the internal plugin manager + */ + @Deprecated + PluginManager getPluginManager(); + + /** + * Gets a plugin of the given type. + * + * @param type the type of the extension + * @return the extension, or <tt>null</tt> if no extension has been installed. + */ + <T> T getContextPlugin(Class<T> type); + + /** + * Allows installation of custom plugins to the Camel context. + * + * @param type the type of the extension + * @param module the instance of the extension + */ + <T> void addContextPlugin(Class<T> type, T module); } diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/PluginManager.java b/core/camel-api/src/main/java/org/apache/camel/spi/PluginManager.java new file mode 100644 index 00000000000..504ca54ab75 --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/spi/PluginManager.java @@ -0,0 +1,36 @@ +/* + * 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.spi; + +public interface PluginManager { + /** + * Gets a plugin of the given type. + * + * @param type the type of the extension + * @return the extension, or <tt>null</tt> if no extension has been installed. + */ + <T> T getContextPlugin(Class<T> type); + + /** + * Allows installation of custom plugins to the Camel context. + * + * @param type the type of the extension + * @param module the instance of the extension + */ + <T> void addContextPlugin(Class<T> type, T module); +} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index 17e696579a7..fbd1ec9333e 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -40,6 +40,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.function.Supplier; import org.apache.camel.CamelContext; @@ -133,6 +134,7 @@ import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.PeriodTaskResolver; import org.apache.camel.spi.PeriodTaskScheduler; +import org.apache.camel.spi.PluginManager; import org.apache.camel.spi.ProcessorExchangeFactory; import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.PropertiesComponent; @@ -271,8 +273,8 @@ public abstract class AbstractCamelContext extends BaseService private final InternalRouteStartupManager internalRouteStartupManager = new InternalRouteStartupManager(this); private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<>(); private final StopWatch stopWatch = new StopWatch(false); - private final Map<Class<?>, Object> extensions = new ConcurrentHashMap<>(); - private final ThreadLocal<Set<String>> componentsInCreation = ThreadLocal.withInitial(HashSet::new); + private final PluginManager pluginManager; + private final ThreadLocal<Set<String>> componentsInCreation = ThreadLocal.withInitial(() -> new HashSet<>()); private VetoCamelContextStartException vetoed; private String managementName; private ClassLoader applicationContextClassLoader; @@ -387,6 +389,7 @@ public abstract class AbstractCamelContext extends BaseService this.bootstraps.add(bootstrapFactories::clear); this.internalServiceManager = new InternalServiceManager(this, internalRouteStartupManager, startupListeners); + this.pluginManager = new DefaultContextPluginManager(internalServiceManager); if (build) { try { @@ -444,38 +447,12 @@ public abstract class AbstractCamelContext extends BaseService return type.cast(this); } - // lookup by direct implementatiin - Object extension = extensions.get(type); - if (extension == null) { - // fallback and lookup via interfaces - for (Object e : extensions.values()) { - if (type.isInstance(e)) { - return type.cast(e); - } - } - } - if (extension instanceof Supplier) { - extension = ((Supplier) extension).get(); - setExtension(type, (T) extension); - } - return (T) extension; + return pluginManager.getContextPlugin(type); } @Override public <T> void setExtension(Class<T> type, T module) { - if (module != null) { - try { - extensions.put(type, internalServiceManager.addService(module)); - } catch (Exception e) { - throw RuntimeCamelException.wrapRuntimeCamelException(e); - } - } - } - - public <T> void setDefaultExtension(Class<T> type, Supplier<T> module) { - if (module != null) { - extensions.putIfAbsent(type, module); - } + pluginManager.addContextPlugin(type, module); } @Override diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java index 2e739885ad3..4aeaa519cd0 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java @@ -80,6 +80,7 @@ import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.PeriodTaskResolver; import org.apache.camel.spi.PeriodTaskScheduler; +import org.apache.camel.spi.PluginManager; import org.apache.camel.spi.ProcessorExchangeFactory; import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.PropertiesComponent; @@ -108,6 +109,7 @@ class DefaultCamelContextExtension implements ExtendedCamelContext { private final List<InterceptStrategy> interceptStrategies = new ArrayList<>(); private final Map<String, FactoryFinder> factories = new ConcurrentHashMap<>(); private final Set<LogListener> logListeners = new LinkedHashSet<>(); + private final PluginManager pluginManager = new DefaultContextPluginManager(); private volatile String description; @Deprecated private ErrorHandlerFactory errorHandlerFactory; @@ -1150,4 +1152,29 @@ class DefaultCamelContextExtension implements ExtendedCamelContext { public String getTestExcludeRoutes() { return camelContext.getTestExcludeRoutes(); } + + @Override + public PluginManager getPluginManager() { + return pluginManager; + } + + @Override + public <T> T getContextPlugin(Class<T> type) { + T ret = pluginManager.getContextPlugin(type); + + // Note: this is because of interfaces like Model which are still tightly coupled with the context + if (ret == null) { + if (type.isInstance(camelContext)) { + return type.cast(camelContext); + } + } + + return ret; + } + + @Override + public <T> void addContextPlugin(Class<T> type, T module) { + final T addedModule = camelContext.getInternalServiceManager().addService(module); + pluginManager.addContextPlugin(type, addedModule); + } } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultContextPluginManager.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultContextPluginManager.java new file mode 100644 index 00000000000..090078ba97d --- /dev/null +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultContextPluginManager.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.camel.impl.engine; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; + +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.PluginManager; + +public class DefaultContextPluginManager implements PluginManager { + private final Map<Class<?>, Object> extensions = new ConcurrentHashMap<>(); + + public DefaultContextPluginManager() { + + } + + @Override + public <T> T getContextPlugin(Class<T> type) { + // lookup by direct implementation + Object extension = extensions.get(type); + if (extension == null) { + // fallback and lookup via interfaces + for (Object e : extensions.values()) { + if (type.isInstance(e)) { + return type.cast(e); + } + } + } + if (extension instanceof Supplier) { + extension = ((Supplier) extension).get(); + addContextPlugin(type, (T) extension); + } + return (T) extension; + } + + @Override + public <T> void addContextPlugin(Class<T> type, T module) { + if (module != null) { + try { + extensions.put(type, module); + } catch (Exception e) { + throw RuntimeCamelException.wrapRuntimeCamelException(e); + } + } + } +} diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContextExtension.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContextExtension.java index 25ed86d82da..6125fdd7fef 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContextExtension.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContextExtension.java @@ -75,6 +75,7 @@ import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.PeriodTaskResolver; import org.apache.camel.spi.PeriodTaskScheduler; +import org.apache.camel.spi.PluginManager; import org.apache.camel.spi.ProcessorExchangeFactory; import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.PropertiesComponent; @@ -893,6 +894,21 @@ class LightweightCamelContextExtension implements ExtendedCamelContext { throw new UnsupportedOperationException(); } + @Override + public PluginManager getPluginManager() { + return camelContext.getCamelContextExtension().getPluginManager(); + } + + @Override + public <T> T getContextPlugin(Class<T> type) { + return camelContext.getCamelContextExtension().getPluginManager().getContextPlugin(type); + } + + @Override + public <T> void addContextPlugin(Class<T> type, T module) { + camelContext.getCamelContextExtension().addContextPlugin(type, module); + } + Endpoint doGetEndpoint(String uri, boolean normalized, boolean prototype) { StringHelper.notEmpty(uri, "uri"); // in case path has property placeholders then try to let property
