Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.RejectedExecutionException;
import org.apache.camel.AsyncCallback;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePropertyKey;
import org.apache.camel.MessageHistory;
import org.apache.camel.NamedNode;
import org.apache.camel.NamedRoute;
import org.apache.camel.NonManagedService;
import org.apache.camel.Ordered;
import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.StatefulService;
import org.apache.camel.StreamCache;
import org.apache.camel.impl.debugger.BacklogTracer;
import org.apache.camel.impl.debugger.DefaultBacklogTracerEventMessage;
import org.apache.camel.spi.BacklogDebugger;
import org.apache.camel.spi.CamelEvent;
import org.apache.camel.spi.CamelInternalProcessorAdvice;
import org.apache.camel.spi.Debugger;
import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.spi.EventNotifier;
import org.apache.camel.spi.InflightRepository;
import org.apache.camel.spi.InternalProcessor;
import org.apache.camel.spi.ManagementInterceptStrategy.InstrumentationProcessor;
import org.apache.camel.spi.MessageHistoryFactory;
import org.apache.camel.spi.PooledObjectFactory;
import org.apache.camel.spi.ReactiveExecutor;
import org.apache.camel.spi.RoutePolicy;
import org.apache.camel.spi.ShutdownStrategy;
import org.apache.camel.spi.StreamCachingStrategy;
import org.apache.camel.spi.Synchronization;
import org.apache.camel.spi.SynchronizationRouteAware;
import org.apache.camel.spi.Tracer;
import org.apache.camel.spi.Transformer;
import org.apache.camel.spi.UnitOfWork;
import org.apache.camel.spi.UnitOfWorkFactory;
import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.support.EventHelper;
import org.apache.camel.support.ExchangeHelper;
import org.apache.camel.support.LoggerHelper;
import org.apache.camel.support.MessageHelper;
import org.apache.camel.support.OrderedComparator;
import org.apache.camel.support.PluginHelper;
import org.apache.camel.support.SimpleEventNotifierSupport;
import org.apache.camel.support.SynchronizationAdapter;
import org.apache.camel.support.UnitOfWorkHelper;
import org.apache.camel.support.processor.DelegateAsyncProcessor;
import org.apache.camel.support.service.ServiceHelper;
import org.apache.camel.util.StopWatch;
import org.apache.camel.util.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.util.Objects.requireNonNull;
/**
* Internal {@link Processor} that Camel routing engine used during routing for cross cutting functionality such as:
*
*
Execute {@link UnitOfWork}
*
Keeping track which route currently is being routed
*
Execute {@link RoutePolicy}
*
Gather JMX performance statics
*
Tracing
*
Debugging
*
Message History
*
Stream Caching
*
{@link Transformer}
*
* ... and more.
*
* This implementation executes this cross cutting functionality as a {@link CamelInternalProcessorAdvice} advice
* (before and after advice) by executing the {@link CamelInternalProcessorAdvice#before(org.apache.camel.Exchange)} and
* {@link CamelInternalProcessorAdvice#after(org.apache.camel.Exchange, Object)} callbacks in correct order during
* routing. This reduces number of stack frames needed during routing, and reduce the number of lines in stacktraces, as
* well makes debugging the routing engine easier for end users.
*
* Debugging tips: Camel end users whom want to debug their Camel applications with the Camel source code, then
* make sure to read the source code of this class about the debugging tips, which you can find in the
* {@link #process(org.apache.camel.Exchange, org.apache.camel.AsyncCallback)} method.
*
* The added advices can implement {@link Ordered} to control in which order the advices are executed.
*/
public class CamelInternalProcessor extends DelegateAsyncProcessor implements InternalProcessor {
private static final Logger LOG = LoggerFactory.getLogger(CamelInternalProcessor.class);
private static final Object[] EMPTY_STATES = new Object[0];
final CamelContext camelContext;
private final ReactiveExecutor reactiveExecutor;
private final ShutdownStrategy shutdownStrategy;
private final List> advices = new ArrayList<>();
private byte statefulAdvices;
private PooledObjectFactory taskFactory;
public CamelInternalProcessor(CamelContext camelContext) {
this.camelContext = camelContext;
this.reactiveExecutor = requireNonNull(camelContext.getCamelContextExtension().getReactiveExecutor());
this.shutdownStrategy = camelContext.getShutdownStrategy();
}
public CamelInternalProcessor(CamelContext camelContext, Processor processor) {
super(processor);
this.camelContext = camelContext;
this.reactiveExecutor = camelContext.getCamelContextExtension().getReactiveExecutor();
this.shutdownStrategy = camelContext.getShutdownStrategy();
}
@Override
protected void doBuild() throws Exception {
boolean pooled = camelContext.getCamelContextExtension().getExchangeFactory().isPooled();
// only create pooled task factory
if (pooled) {
taskFactory = new CamelInternalPooledTaskFactory();
int capacity = camelContext.getCamelContextExtension().getExchangeFactory().getCapacity();
taskFactory.setCapacity(capacity);
LOG.trace("Using TaskFactory: {}", taskFactory);
}
ServiceHelper.buildService(taskFactory, processor);
}
@Override
protected void doShutdown() throws Exception {
super.doShutdown();
ServiceHelper.stopAndShutdownServices(taskFactory, processor);
}
@Override
public void addAdvice(CamelInternalProcessorAdvice> advice) {
advices.add(advice);
// ensure advices are sorted so they are in the order we want
advices.sort(OrderedComparator.get());
if (advice.hasState()) {
statefulAdvices++;
}
}
@Override
public T getAdvice(Class type) {
for (CamelInternalProcessorAdvice> task : advices) {
Object advice = unwrap(task);
if (type.isInstance(advice)) {
return type.cast(advice);
}
}
return null;
}
@Override
public void addRoutePolicyAdvice(List routePolicyList) {
addAdvice(new CamelInternalProcessor.RoutePolicyAdvice(routePolicyList));
}
@Override
public void addRouteInflightRepositoryAdvice(InflightRepository inflightRepository, String routeId) {
addAdvice(new CamelInternalProcessor.RouteInflightRepositoryAdvice(camelContext.getInflightRepository(), routeId));
}
@Override
public void addRouteLifecycleAdvice() {
addAdvice(new CamelInternalProcessor.RouteLifecycleAdvice());
}
@Override
public void addManagementInterceptStrategy(InstrumentationProcessor processor) {
addAdvice(CamelInternalProcessor.wrap(processor));
}
@Override
public void setRouteOnAdvices(Route route) {
RoutePolicyAdvice task = getAdvice(RoutePolicyAdvice.class);
if (task != null) {
task.setRoute(route);
}
RouteLifecycleAdvice task2 = getAdvice(RouteLifecycleAdvice.class);
if (task2 != null) {
task2.setRoute(route);
}
}
/**
* Callback task to process the advices after processing.
*/
private final class AsyncAfterTask implements CamelInternalTask {
private final Object[] states;
private Exchange exchange;
private AsyncCallback originalCallback;
private AsyncAfterTask(Object[] states) {
this.states = states;
}
@Override
public void prepare(Exchange exchange, AsyncCallback originalCallback) {
this.exchange = exchange;
this.originalCallback = originalCallback;
}
@Override
public Object[] getStates() {
return states;
}
@Override
public void reset() {
Arrays.fill(this.states, null);
this.exchange = null;
this.originalCallback = null;
}
@Override
public void done(boolean doneSync) {
try {
AdviceIterator.runAfterTasks(advices, states, exchange);
} finally {
// ----------------------------------------------------------
// CAMEL END USER - DEBUG ME HERE +++ START +++
// ----------------------------------------------------------
// callback must be called
if (originalCallback != null) {
reactiveExecutor.schedule(originalCallback);
}
// ----------------------------------------------------------
// CAMEL END USER - DEBUG ME HERE +++ END +++
// ----------------------------------------------------------
// task is done so reset
if (taskFactory != null) {
taskFactory.release(this);
}
}
}
}
@Override
public boolean process(Exchange exchange, AsyncCallback originalCallback) {
// ----------------------------------------------------------
// CAMEL END USER - READ ME FOR DEBUGGING TIPS
// ----------------------------------------------------------
// If you want to debug the Camel routing engine, then there is a lot of internal functionality
// the routing engine executes during routing messages. You can skip debugging this internal
// functionality and instead debug where the routing engine continues routing to the next node
// in the routes. The CamelInternalProcessor is a vital part of the routing engine, as its
// being used in between the nodes. As an end user you can just debug the code in this class
// in between the:
// CAMEL END USER - DEBUG ME HERE +++ START +++
// CAMEL END USER - DEBUG ME HERE +++ END +++
// you can see in the code below within the processTransacted or processNonTransacted methods.
// ----------------------------------------------------------
if (processor == null || exchange.isRouteStop()) {
// no processor or we should not continue then we are done
originalCallback.done(true);
return true;
}
if (shutdownStrategy.isForceShutdown()) {
return processShutdown(exchange, originalCallback);
}
Object[] states;
// create internal callback which will execute the advices in reverse order when done
CamelInternalTask afterTask = taskFactory != null ? taskFactory.acquire() : null;
if (afterTask == null) {
states = statefulAdvices > 0 ? new Object[statefulAdvices] : EMPTY_STATES;
afterTask = new AsyncAfterTask(states);
} else {
states = afterTask.getStates();
}
afterTask.prepare(exchange, originalCallback);
// optimise to use object array for states, and only for the number of advices that keep state
// optimise for loop using index access to avoid creating iterator object
for (int i = 0, j = 0; i < advices.size(); i++) {
CamelInternalProcessorAdvice> task = advices.get(i);
try {
Object state = task.before(exchange);
if (task.hasState()) {
states[j++] = state;
}
} catch (Exception e) {
return handleException(exchange, originalCallback, e, afterTask);
}
}
if (exchange.isTransacted()) {
return processTransacted(exchange, afterTask);
}
return processNonTransacted(exchange, afterTask);
}
private static boolean processShutdown(Exchange exchange, AsyncCallback originalCallback) {
String msg = "Run not allowed as ShutdownStrategy is forcing shutting down, will reject executing exchange: "
+ exchange;
LOG.debug(msg);
if (exchange.getException() == null) {
exchange.setException(new RejectedExecutionException(msg));
}
// force shutdown so we should not continue
originalCallback.done(true);
return true;
}
private boolean processNonTransacted(Exchange exchange, CamelInternalTask afterTask) {
final AsyncCallback async = beforeProcess(exchange, afterTask);
// ----------------------------------------------------------
// CAMEL END USER - DEBUG ME HERE +++ START +++
// ----------------------------------------------------------
if (LOG.isTraceEnabled()) {
LOG.trace("Processing exchange for exchangeId: {} -> {}", exchange.getExchangeId(), exchange);
}
boolean sync = processor.process(exchange, async);
if (!sync) {
EventHelper.notifyExchangeAsyncProcessingStartedEvent(camelContext, exchange);
}
// ----------------------------------------------------------
// CAMEL END USER - DEBUG ME HERE +++ END +++
// ----------------------------------------------------------
// CAMEL-18255: move uow.afterProcess handling to the callback
if (LOG.isTraceEnabled()) {
logExchangeContinuity(exchange, sync);
}
return sync;
}
private static void logExchangeContinuity(Exchange exchange, boolean sync) {
LOG.trace("Exchange processed and is continued routed {} for exchangeId: {} -> {}",
sync ? "synchronously" : "asynchronously",
exchange.getExchangeId(), exchange);
}
private AsyncCallback beforeProcess(Exchange exchange, CamelInternalTask afterTask) {
final UnitOfWork uow = exchange.getUnitOfWork();
// optimize to only do before uow processing if really needed
if (uow != null && uow.isBeforeAfterProcess()) {
return uow.beforeProcess(processor, exchange, afterTask);
}
return afterTask;
}
private boolean processTransacted(Exchange exchange, CamelInternalTask afterTask) {
// must be synchronized for transacted exchanges
if (LOG.isTraceEnabled()) {
LOG.trace("Transacted Exchange must be routed synchronously for exchangeId: {} -> {}", exchange.getExchangeId(),
exchange);
}
try {
// ----------------------------------------------------------
// CAMEL END USER - DEBUG ME HERE +++ START +++
// ----------------------------------------------------------
processor.process(exchange);
// ----------------------------------------------------------
// CAMEL END USER - DEBUG ME HERE +++ END +++
// ----------------------------------------------------------
} catch (Exception e) {
exchange.setException(e);
} finally {
// processing is done
afterTask.done(true);
}
// we are done synchronously - must return true
return true;
}
private boolean handleException(
Exchange exchange, AsyncCallback originalCallback, Exception e, CamelInternalTask afterTask) {
// error in before so break out
exchange.setException(e);
try {
originalCallback.done(true);
} finally {
// task is done so reset
if (taskFactory != null) {
taskFactory.release(afterTask);
}
}
return true;
}
@Override
public String toString() {
return processor != null ? processor.toString() : super.toString();
}
/**
* Advice to invoke callbacks for before and after routing.
*/
public static class RouteLifecycleAdvice implements CamelInternalProcessorAdvice