org.apache.camel.impl.engine.DefaultRoute Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-base-engine Show documentation
Show all versions of camel-base-engine Show documentation
The Base Engine Camel Framework
The newest version!
/*
* 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.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
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.Channel;
import org.apache.camel.Consumer;
import org.apache.camel.Endpoint;
import org.apache.camel.ErrorHandlerFactory;
import org.apache.camel.NamedNode;
import org.apache.camel.Navigate;
import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.RouteAware;
import org.apache.camel.Service;
import org.apache.camel.ShutdownRoute;
import org.apache.camel.ShutdownRunningTask;
import org.apache.camel.Suspendable;
import org.apache.camel.SuspendableService;
import org.apache.camel.resume.ConsumerListener;
import org.apache.camel.resume.ConsumerListenerAware;
import org.apache.camel.resume.ResumeAdapter;
import org.apache.camel.resume.ResumeAware;
import org.apache.camel.resume.ResumeStrategy;
import org.apache.camel.spi.IdAware;
import org.apache.camel.spi.InterceptStrategy;
import org.apache.camel.spi.ManagementInterceptStrategy;
import org.apache.camel.spi.Resource;
import org.apache.camel.spi.RouteController;
import org.apache.camel.spi.RouteError;
import org.apache.camel.spi.RouteIdAware;
import org.apache.camel.spi.RoutePolicy;
import org.apache.camel.support.LoggerHelper;
import org.apache.camel.support.PatternHelper;
import org.apache.camel.support.resume.AdapterHelper;
import org.apache.camel.support.service.ServiceHelper;
import org.apache.camel.support.service.ServiceSupport;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.StopWatch;
import org.apache.camel.util.TimeUtils;
/**
* Default implementation of {@link Route}.
*
* Use the API from {@link org.apache.camel.CamelContext} to control the lifecycle of a route, such as starting and
* stopping using the {@link org.apache.camel.spi.RouteController#startRoute(String)} and
* {@link org.apache.camel.spi.RouteController#stopRoute(String)} methods.
*/
public class DefaultRoute extends ServiceSupport implements Route {
private final CamelContext camelContext;
private NamedNode route;
private final String routeId;
private final String routeDescription;
private final Resource sourceResource;
private final String sourceLocation;
private final String sourceLocationShort;
private final List eventDrivenProcessors = new ArrayList<>();
private final List interceptStrategies = new ArrayList<>(0);
private ManagementInterceptStrategy managementInterceptStrategy;
private Boolean trace;
private Boolean backlogTrace;
private Boolean debug;
private Boolean messageHistory;
private Boolean logMask;
private Boolean logExhaustedMessageBody;
private Boolean streamCache;
private Long delay;
private Boolean autoStartup = Boolean.TRUE;
private final List routePolicyList = new ArrayList<>();
private ShutdownRoute shutdownRoute;
private ShutdownRunningTask shutdownRunningTask;
private final Map onCompletions = new HashMap<>();
private final Map onExceptions = new HashMap<>();
private ResumeStrategy resumeStrategy;
private ConsumerListener, ?> consumerListener;
// camel-core-model
@Deprecated(since = "3.17.0")
private ErrorHandlerFactory errorHandlerFactory;
// camel-core-model: must be concurrent as error handlers can be mutated concurrently via multicast/recipientlist EIPs
private final ConcurrentMap> errorHandlers = new ConcurrentHashMap<>();
private final Endpoint endpoint;
private final Map properties = new HashMap<>();
private final List services = new ArrayList<>();
private final List servicesToStop = new ArrayList<>();
private final StopWatch stopWatch = new StopWatch(false);
private RouteError routeError;
private Integer startupOrder;
private RouteController routeController;
private Processor processor;
private Consumer consumer;
public DefaultRoute(CamelContext camelContext, NamedNode route, String routeId,
String routeDescription, Endpoint endpoint, Resource resource) {
this.camelContext = camelContext;
this.route = route;
this.routeId = routeId;
this.routeDescription = routeDescription;
this.endpoint = endpoint;
this.sourceResource = resource;
this.sourceLocation = LoggerHelper.getSourceLocation(route);
this.sourceLocationShort = LoggerHelper.getLineNumberLoggerName(route);
}
@Override
public String getId() {
return routeId;
}
@Override
public String getNodePrefixId() {
return (String) properties.get(Route.NODE_PREFIX_ID_PROPERTY);
}
@Override
public boolean isCustomId() {
return "true".equals(properties.get(Route.CUSTOM_ID_PROPERTY));
}
@Override
public boolean isCreatedByRestDsl() {
return "true".equals(properties.get(Route.REST_PROPERTY));
}
@Override
public boolean isCreatedByRouteTemplate() {
return "true".equals(properties.get(Route.TEMPLATE_PROPERTY));
}
@Override
public boolean isCreatedByKamelet() {
return "true".equals(properties.get(Route.KAMELET_PROPERTY));
}
@Override
public String getGroup() {
return (String) properties.get(Route.GROUP_PROPERTY);
}
@Override
public String getUptime() {
long delta = getUptimeMillis();
if (delta == 0) {
return "";
}
return TimeUtils.printDuration(delta);
}
@Override
public long getUptimeMillis() {
return stopWatch.taken();
}
@Override
public Endpoint getEndpoint() {
return endpoint;
}
@Override
public CamelContext getCamelContext() {
return camelContext;
}
@Override
public Map getProperties() {
return properties;
}
@Override
public String getDescription() {
Object value = properties.get(Route.DESCRIPTION_PROPERTY);
return value != null ? (String) value : null;
}
@Override
public String getConfigurationId() {
Object value = properties.get(Route.CONFIGURATION_ID_PROPERTY);
return value != null ? (String) value : null;
}
@Override
public Resource getSourceResource() {
return sourceResource;
}
@Override
public String getSourceLocation() {
return sourceLocation;
}
@Override
public String getSourceLocationShort() {
return sourceLocationShort;
}
@Override
public void initializeServices() throws Exception {
services.clear();
// gather all the services for this route
gatherServices(services);
}
@Override
public List getServices() {
return services;
}
@Override
public void addService(Service service) {
if (!services.contains(service)) {
services.add(service);
}
}
@Override
public void addService(Service service, boolean forceStop) {
if (forceStop) {
if (!servicesToStop.contains(service)) {
servicesToStop.add(service);
}
} else {
addService(service);
}
}
@Override
public void warmUp() {
// noop
}
/**
* Do not invoke this method directly, use {@link org.apache.camel.spi.RouteController#startRoute(String)} to start
* a route.
*/
@Override
public void start() {
super.start();
}
/**
* Do not invoke this method directly, use {@link org.apache.camel.spi.RouteController#stopRoute(String)} to stop a
* route.
*/
@Override
public void stop() {
super.stop();
}
@Override
protected void doStart() throws Exception {
stopWatch.restart();
}
@Override
protected void doStop() throws Exception {
// and clear start date
stopWatch.stop();
}
@Override
protected void doShutdown() throws Exception {
// clear services when shutting down
services.clear();
// shutdown forced services
ServiceHelper.stopAndShutdownService(servicesToStop);
servicesToStop.clear();
}
@Override
public RouteError getLastError() {
return routeError;
}
@Override
public void setLastError(RouteError routeError) {
this.routeError = routeError;
}
@Override
public Integer getStartupOrder() {
return startupOrder;
}
@Override
public void setStartupOrder(Integer startupOrder) {
this.startupOrder = startupOrder;
}
@Override
public RouteController getRouteController() {
return routeController;
}
@Override
public void setRouteController(RouteController routeController) {
this.routeController = routeController;
}
@Override
public Boolean isAutoStartup() {
return autoStartup;
}
@Override
public void setAutoStartup(Boolean autoStartup) {
this.autoStartup = autoStartup;
}
@Override
public NamedNode getRoute() {
return route;
}
@Override
public void clearRouteModel() {
route = null;
errorHandlerFactory = null;
errorHandlers.clear();
}
@Override
public String getRouteId() {
return routeId;
}
@Override
public String getRouteDescription() {
return routeDescription;
}
@Override
public List getEventDrivenProcessors() {
return eventDrivenProcessors;
}
@Override
public List getInterceptStrategies() {
return interceptStrategies;
}
@Override
public void setManagementInterceptStrategy(ManagementInterceptStrategy interceptStrategy) {
this.managementInterceptStrategy = interceptStrategy;
}
@Override
public ManagementInterceptStrategy getManagementInterceptStrategy() {
return managementInterceptStrategy;
}
@Override
public void setTracing(Boolean tracing) {
this.trace = tracing;
}
@Override
public Boolean isTracing() {
if (trace != null) {
return trace;
} else {
// fallback to the option from camel context
return camelContext.isTracing();
}
}
@Override
public String getTracingPattern() {
// can only set this on context level
return camelContext.getTracingPattern();
}
@Override
public void setTracingPattern(String tracePattern) {
// can only set this on context level
camelContext.setTracingPattern(tracePattern);
}
@Override
public void setBacklogTracing(Boolean backlogTrace) {
this.backlogTrace = backlogTrace;
}
@Override
public Boolean isBacklogTracing() {
if (backlogTrace != null) {
return backlogTrace;
} else {
// fallback to the option from camel context
return camelContext.isBacklogTracing();
}
}
@Override
public void setDebugging(Boolean debugging) {
this.debug = debugging;
}
@Override
public Boolean isDebugging() {
if (debug != null) {
return debug;
} else {
// fallback to the option from camel context
return camelContext.isDebugging();
}
}
@Override
public void setMessageHistory(Boolean messageHistory) {
this.messageHistory = messageHistory;
}
@Override
public Boolean isMessageHistory() {
if (messageHistory != null) {
return messageHistory;
} else {
// fallback to the option from camel context
return camelContext.isMessageHistory();
}
}
@Override
public void setLogMask(Boolean logMask) {
this.logMask = logMask;
}
@Override
public Boolean isLogMask() {
if (logMask != null) {
return logMask;
} else {
// fallback to the option from camel context
return camelContext.isLogMask();
}
}
@Override
public void setLogExhaustedMessageBody(Boolean logExhaustedMessageBody) {
this.logExhaustedMessageBody = logExhaustedMessageBody;
}
@Override
public Boolean isLogExhaustedMessageBody() {
if (logExhaustedMessageBody != null) {
return logExhaustedMessageBody;
} else {
// fallback to the option from camel context
return camelContext.isLogExhaustedMessageBody();
}
}
@Override
public void setStreamCaching(Boolean cache) {
this.streamCache = cache;
}
@Override
public Boolean isStreamCaching() {
if (streamCache != null) {
return streamCache;
} else {
// fallback to the option from camel context
return camelContext.isStreamCaching();
}
}
@Override
public void setDelayer(Long delay) {
this.delay = delay;
}
@Override
public Long getDelayer() {
if (delay != null) {
return delay;
} else {
// fallback to the option from camel context
return camelContext.getDelayer();
}
}
@Override
public void setErrorHandlerFactory(ErrorHandlerFactory errorHandlerFactory) {
this.errorHandlerFactory = errorHandlerFactory;
}
@Override
public ErrorHandlerFactory getErrorHandlerFactory() {
return errorHandlerFactory;
}
@Override
public void setShutdownRoute(ShutdownRoute shutdownRoute) {
this.shutdownRoute = shutdownRoute;
}
@Override
public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) {
// can only be configured on CamelContext
camelContext.setAllowUseOriginalMessage(allowUseOriginalMessage);
}
@Override
public Boolean isAllowUseOriginalMessage() {
// can only be configured on CamelContext
return camelContext.isAllowUseOriginalMessage();
}
@Override
public Boolean isCaseInsensitiveHeaders() {
// can only be configured on CamelContext
return camelContext.isCaseInsensitiveHeaders();
}
@Override
public void setCaseInsensitiveHeaders(Boolean caseInsensitiveHeaders) {
// can only be configured on CamelContext
camelContext.setCaseInsensitiveHeaders(caseInsensitiveHeaders);
}
@Override
public Boolean isAutowiredEnabled() {
// can only be configured on CamelContext
return camelContext.isAutowiredEnabled();
}
@Override
public void setAutowiredEnabled(Boolean autowiredEnabled) {
// can only be configured on CamelContext
camelContext.setAutowiredEnabled(autowiredEnabled);
}
@Override
public ShutdownRoute getShutdownRoute() {
if (shutdownRoute != null) {
return shutdownRoute;
} else {
// fallback to the option from camel context
return camelContext.getShutdownRoute();
}
}
@Override
public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) {
this.shutdownRunningTask = shutdownRunningTask;
}
@Override
public ShutdownRunningTask getShutdownRunningTask() {
if (shutdownRunningTask != null) {
return shutdownRunningTask;
} else {
// fallback to the option from camel context
return camelContext.getShutdownRunningTask();
}
}
@Override
public List getRoutePolicyList() {
return routePolicyList;
}
@Override
public Collection getOnCompletions() {
return onCompletions.values();
}
@Override
public void setOnCompletion(String onCompletionId, Processor processor) {
onCompletions.put(onCompletionId, processor);
}
@Override
public Collection getOnExceptions() {
return onExceptions.values();
}
@Override
public Processor getOnException(String onExceptionId) {
return onExceptions.get(onExceptionId);
}
@Override
public void setOnException(String onExceptionId, Processor processor) {
onExceptions.put(onExceptionId, processor);
}
@Override
public Set getErrorHandlers(ErrorHandlerFactory factory) {
return errorHandlers.computeIfAbsent(factory, f -> new LinkedHashSet<>());
}
@Override
public void addErrorHandler(ErrorHandlerFactory factory, NamedNode onException) {
errorHandlers.computeIfAbsent(factory, f -> new LinkedHashSet<>()).add(onException);
}
@Override
public void addErrorHandlerFactoryReference(ErrorHandlerFactory source, ErrorHandlerFactory target) {
Set list = errorHandlers.computeIfAbsent(source, f -> new LinkedHashSet<>());
Set previous = errorHandlers.put(target, list);
if (list != previous && ObjectHelper.isNotEmpty(previous) && ObjectHelper.isNotEmpty(list)) {
throw new IllegalStateException("Multiple references with different handlers");
}
}
@Override
public String toString() {
return "Route[" + getEndpoint() + " -> " + processor + "]";
}
@Override
public Processor getProcessor() {
return processor;
}
@Override
public void setProcessor(Processor processor) {
this.processor = processor;
}
/**
* Factory method to lazily create the complete list of services required for this route such as adding the
* processor or consumer
*/
protected void gatherServices(List services) throws Exception {
// first gather the root services
gatherRootServices(services);
// and then all the child services
List children = new ArrayList<>();
for (Service service : services) {
Set extra = ServiceHelper.getChildServices(service);
children.addAll(extra);
}
for (Service extra : children) {
if (!services.contains(extra)) {
services.add(extra);
}
}
}
private void gatherRootServices(List services) throws Exception {
Endpoint endpoint = getEndpoint();
consumer = endpoint.createConsumer(processor);
if (consumer != null) {
services.add(consumer);
if (consumer instanceof RouteAware routeAware) {
routeAware.setRoute(this);
}
if (consumer instanceof RouteIdAware routeIdAware) {
routeIdAware.setRouteId(this.getId());
}
if (consumer instanceof ResumeAware resumeAware && resumeStrategy != null) {
ResumeAdapter resumeAdapter = AdapterHelper.eval(getCamelContext(), resumeAware, resumeStrategy);
resumeStrategy.setAdapter(resumeAdapter);
resumeAware.setResumeStrategy(resumeStrategy);
}
if (consumer instanceof ConsumerListenerAware consumerListenerAware) {
consumerListenerAware.setConsumerListener(consumerListener);
}
}
if (processor instanceof Service service) {
services.add(service);
}
for (Processor p : onCompletions.values()) {
if (processor instanceof Service service) {
services.add(service);
}
}
for (Processor p : onExceptions.values()) {
if (processor instanceof Service service) {
services.add(service);
}
}
}
@Override
@SuppressWarnings("unchecked")
public Navigate navigate() {
Processor answer = getProcessor();
// we want to navigate routes to be easy, so skip the initial channel
// and navigate to its output where it all starts from end user point of view
if (answer instanceof Navigate nav) {
if (nav.next().size() == 1) {
Object first = nav.next().get(0);
if (first instanceof Navigate) {
return (Navigate) first;
}
}
return (Navigate) answer;
}
return null;
}
@Override
public List filter(String pattern) {
List match = new ArrayList<>();
doFilter(pattern, navigate(), match);
return match;
}
@SuppressWarnings("unchecked")
private void doFilter(String pattern, Navigate nav, List match) {
List list = nav.next();
if (list != null) {
for (Processor proc : list) {
if (proc instanceof Channel channel) {
proc = channel.getNextProcessor();
}
String id = null;
if (proc instanceof IdAware idAware) {
id = idAware.getId();
}
if (PatternHelper.matchPattern(id, pattern)) {
match.add(proc);
}
if (proc instanceof Navigate) {
Navigate child = (Navigate) proc;
doFilter(pattern, child, match);
}
}
}
}
@Override
public Consumer getConsumer() {
return consumer;
}
@Override
public boolean supportsSuspension() {
return consumer instanceof Suspendable && consumer instanceof SuspendableService;
}
@Override
public void setResumeStrategy(ResumeStrategy resumeStrategy) {
this.resumeStrategy = resumeStrategy;
}
@Override
public void setConsumerListener(ConsumerListener, ?> consumerListener) {
this.consumerListener = consumerListener;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy