001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.processor;
018
019import java.io.Serializable;
020import java.util.Random;
021
022import org.apache.camel.Exchange;
023import org.apache.camel.LoggingLevel;
024import org.apache.camel.Predicate;
025import org.apache.camel.util.ObjectHelper;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029/**
030 * The policy used to decide how many times to redeliver and the time between
031 * the redeliveries before being sent to a <a
032 * href="http://camel.apache.org/dead-letter-channel.html">Dead Letter
033 * Channel</a>
034 * <p>
035 * The default values are:
036 * <ul>
037 *   <li>maximumRedeliveries = 0</li>
038 *   <li>redeliveryDelay = 1000L (the initial delay)</li>
039 *   <li>maximumRedeliveryDelay = 60 * 1000L</li>
040 *   <li>asyncDelayedRedelivery = false</li>
041 *   <li>backOffMultiplier = 2</li>
042 *   <li>useExponentialBackOff = false</li>
043 *   <li>collisionAvoidanceFactor = 0.15d</li>
044 *   <li>useCollisionAvoidance = false</li>
045 *   <li>retriesExhaustedLogLevel = LoggingLevel.ERROR</li>
046 *   <li>retryAttemptedLogLevel = LoggingLevel.DEBUG</li>
047 *   <li>retryAttemptedLogInterval = 1</li>
048 *   <li>logRetryAttempted = true</li>
049 *   <li>logRetryStackTrace = false</li>
050 *   <li>logStackTrace = true</li>
051 *   <li>logHandled = false</li>
052 *   <li>logExhausted = true</li>
053 *   <li>logExhaustedMessageHistory = true</li>
054 *   <li>logExhaustedMessageBody = false</li>
055 *   <li>logNewException = true</li>
056 *   <li>allowRedeliveryWhileStopping = true</li>
057 * </ul>
058 * <p/>
059 * Setting the maximumRedeliveries to a negative value such as -1 will then always redeliver (unlimited).
060 * Setting the maximumRedeliveries to 0 will disable redelivery.
061 * <p/>
062 * This policy can be configured either by one of the following two settings:
063 * <ul>
064 *   <li>using conventional options, using all the options defined above</li>
065 *   <li>using delay pattern to declare intervals for delays</li>
066 * </ul>
067 * <p/>
068 * <b>Note:</b> If using delay patterns then the following options is not used (delay, backOffMultiplier, useExponentialBackOff, useCollisionAvoidance)
069 * <p/>
070 * <b>Using delay pattern</b>:
071 * <br/>The delay pattern syntax is: <tt>limit:delay;limit 2:delay 2;limit 3:delay 3;...;limit N:delay N</tt>.
072 * <p/>
073 * How it works is best illustrate with an example with this pattern: <tt>delayPattern=5:1000;10:5000:20:20000</tt>
074 * <br/>The delays will be for attempt in range 0..4 = 0 millis, 5..9 = 1000 millis, 10..19 = 5000 millis, >= 20 = 20000 millis.
075 * <p/>
076 * If you want to set a starting delay, then use 0 as the first limit, eg: <tt>0:1000;5:5000</tt> will use 1 sec delay
077 * until attempt number 5 where it will use 5 seconds going forward.
078 *
079 * @version 
080 */
081public class RedeliveryPolicy implements Cloneable, Serializable {
082    protected static Random randomNumberGenerator;
083    private static final long serialVersionUID = -338222777701473252L;
084    private static final Logger LOG = LoggerFactory.getLogger(RedeliveryPolicy.class);
085
086    protected long redeliveryDelay = 1000L;
087    protected int maximumRedeliveries;
088    protected long maximumRedeliveryDelay = 60 * 1000L;
089    protected double backOffMultiplier = 2;
090    protected boolean useExponentialBackOff;
091    // +/-15% for a 30% spread -cgs
092    protected double collisionAvoidanceFactor = 0.15d;
093    protected boolean useCollisionAvoidance;
094    protected LoggingLevel retriesExhaustedLogLevel = LoggingLevel.ERROR;
095    protected LoggingLevel retryAttemptedLogLevel = LoggingLevel.DEBUG;
096    protected int retryAttemptedLogInterval = 1;
097    protected boolean logStackTrace = true;
098    protected boolean logRetryStackTrace;
099    protected boolean logHandled;
100    protected boolean logContinued;
101    protected boolean logExhausted = true;
102    protected boolean logNewException = true;
103    protected Boolean logExhaustedMessageHistory;
104    protected Boolean logExhaustedMessageBody;
105    protected boolean logRetryAttempted = true;
106    protected String delayPattern;
107    protected boolean asyncDelayedRedelivery;
108    protected boolean allowRedeliveryWhileStopping = true;
109    protected String exchangeFormatterRef;
110
111    public RedeliveryPolicy() {
112    }
113
114    @Override
115    public String toString() {
116        return "RedeliveryPolicy[maximumRedeliveries=" + maximumRedeliveries
117            + ", redeliveryDelay=" + redeliveryDelay
118            + ", maximumRedeliveryDelay=" + maximumRedeliveryDelay
119            + ", asyncDelayedRedelivery=" + asyncDelayedRedelivery
120            + ", allowRedeliveryWhileStopping=" + allowRedeliveryWhileStopping
121            + ", retriesExhaustedLogLevel=" + retriesExhaustedLogLevel
122            + ", retryAttemptedLogLevel=" + retryAttemptedLogLevel
123            + ", retryAttemptedLogInterval=" + retryAttemptedLogInterval
124            + ", logRetryAttempted=" + logRetryAttempted
125            + ", logStackTrace=" + logStackTrace
126            + ", logRetryStackTrace=" + logRetryStackTrace
127            + ", logHandled=" + logHandled
128            + ", logContinued=" + logContinued
129            + ", logExhausted=" + logExhausted
130            + ", logNewException=" + logNewException
131            + ", logExhaustedMessageHistory=" + logExhaustedMessageHistory
132            + ", logExhaustedMessageBody=" + logExhaustedMessageBody
133            + ", useExponentialBackOff="  + useExponentialBackOff
134            + ", backOffMultiplier=" + backOffMultiplier
135            + ", useCollisionAvoidance=" + useCollisionAvoidance
136            + ", collisionAvoidanceFactor=" + collisionAvoidanceFactor
137            + ", delayPattern=" + delayPattern 
138            + ", exchangeFormatterRef=" + exchangeFormatterRef + "]";
139    }
140
141    public RedeliveryPolicy copy() {
142        try {
143            return (RedeliveryPolicy)clone();
144        } catch (CloneNotSupportedException e) {
145            throw new RuntimeException("Could not clone: " + e, e);
146        }
147    }
148
149    /**
150     * Returns true if the policy decides that the message exchange should be
151     * redelivered.
152     *
153     * @param exchange  the current exchange
154     * @param redeliveryCounter  the current retry counter
155     * @param retryWhile  an optional predicate to determine if we should redeliver or not
156     * @return true to redeliver, false to stop
157     */
158    public boolean shouldRedeliver(Exchange exchange, int redeliveryCounter, Predicate retryWhile) {
159        // predicate is always used if provided
160        if (retryWhile != null) {
161            return retryWhile.matches(exchange);
162        }
163
164        if (getMaximumRedeliveries() < 0) {
165            // retry forever if negative value
166            return true;
167        }
168        // redeliver until we hit the max
169        return redeliveryCounter <= getMaximumRedeliveries();
170    }
171
172
173    /**
174     * Calculates the new redelivery delay based on the last one and then <b>sleeps</b> for the necessary amount of time.
175     * <p/>
176     * This implementation will block while sleeping.
177     *
178     * @param redeliveryDelay  previous redelivery delay
179     * @param redeliveryCounter  number of previous redelivery attempts
180     * @return the calculate delay
181     * @throws InterruptedException is thrown if the sleep is interrupted likely because of shutdown
182     */
183    public long sleep(long redeliveryDelay, int redeliveryCounter) throws InterruptedException {
184        redeliveryDelay = calculateRedeliveryDelay(redeliveryDelay, redeliveryCounter);
185
186        if (redeliveryDelay > 0) {
187            sleep(redeliveryDelay);
188        }
189        return redeliveryDelay;
190    }
191
192    /**
193     * Sleeps for the given delay
194     *
195     * @param redeliveryDelay  the delay
196     * @throws InterruptedException is thrown if the sleep is interrupted likely because of shutdown
197     */
198    public void sleep(long redeliveryDelay) throws InterruptedException {
199        LOG.debug("Sleeping for: {} millis until attempting redelivery", redeliveryDelay);
200        Thread.sleep(redeliveryDelay);
201    }
202
203    /**
204     * Calculates the new redelivery delay based on the last one
205     *
206     * @param previousDelay  previous redelivery delay
207     * @param redeliveryCounter  number of previous redelivery attempts
208     * @return the calculate delay
209     */
210    public long calculateRedeliveryDelay(long previousDelay, int redeliveryCounter) {
211        if (ObjectHelper.isNotEmpty(delayPattern)) {
212            // calculate delay using the pattern
213            return calculateRedeliverDelayUsingPattern(delayPattern, redeliveryCounter);
214        }
215
216        // calculate the delay using the conventional parameters
217        long redeliveryDelayResult;
218        if (previousDelay == 0) {
219            redeliveryDelayResult = redeliveryDelay;
220        } else if (useExponentialBackOff && backOffMultiplier > 1) {
221            redeliveryDelayResult = Math.round(backOffMultiplier * previousDelay);
222        } else {
223            redeliveryDelayResult = previousDelay;
224        }
225
226        if (useCollisionAvoidance) {
227
228            /*
229             * First random determines +/-, second random determines how far to
230             * go in that direction. -cgs
231             */
232            Random random = getRandomNumberGenerator();
233            double variance = (random.nextBoolean() ? collisionAvoidanceFactor : -collisionAvoidanceFactor)
234                              * random.nextDouble();
235            redeliveryDelayResult += redeliveryDelayResult * variance;
236        }
237
238        // ensure the calculated result is not bigger than the max delay (if configured)
239        if (maximumRedeliveryDelay > 0 && redeliveryDelayResult > maximumRedeliveryDelay) {
240            redeliveryDelayResult = maximumRedeliveryDelay;
241        }
242
243        return redeliveryDelayResult;
244    }
245
246    /**
247     * Calculates the delay using the delay pattern
248     */
249    protected static long calculateRedeliverDelayUsingPattern(String delayPattern, int redeliveryCounter) {
250        String[] groups = delayPattern.split(";");
251        // find the group where the redelivery counter matches
252        long answer = 0;
253        for (String group : groups) {
254            long delay = Long.valueOf(ObjectHelper.after(group, ":"));
255            int count = Integer.valueOf(ObjectHelper.before(group, ":"));
256            if (count > redeliveryCounter) {
257                break;
258            } else {
259                answer = delay;
260            }
261        }
262
263        return answer;
264    }
265
266    // Builder methods
267    // -------------------------------------------------------------------------
268
269    /**
270     * Sets the initial redelivery delay in milliseconds
271     *
272     * @deprecated will be removed in the near future. Instead use {@link #redeliveryDelay(long)} instead
273     */
274    @Deprecated
275    public RedeliveryPolicy redeliverDelay(long delay) {
276        return redeliveryDelay(delay);
277    }
278
279    /**
280     * Sets the initial redelivery delay in milliseconds
281     */
282    public RedeliveryPolicy redeliveryDelay(long delay) {
283        setRedeliveryDelay(delay);
284        return this;
285    }
286
287    /**
288     * Sets the maximum number of times a message exchange will be redelivered
289     */
290    public RedeliveryPolicy maximumRedeliveries(int maximumRedeliveries) {
291        setMaximumRedeliveries(maximumRedeliveries);
292        return this;
293    }
294
295    /**
296     * Enables collision avoidance which adds some randomization to the backoff
297     * timings to reduce contention probability
298     */
299    public RedeliveryPolicy useCollisionAvoidance() {
300        setUseCollisionAvoidance(true);
301        return this;
302    }
303
304    /**
305     * Enables exponential backoff using the {@link #getBackOffMultiplier()} to
306     * increase the time between retries
307     */
308    public RedeliveryPolicy useExponentialBackOff() {
309        setUseExponentialBackOff(true);
310        return this;
311    }
312
313    /**
314     * Enables exponential backoff and sets the multiplier used to increase the
315     * delay between redeliveries
316     */
317    public RedeliveryPolicy backOffMultiplier(double multiplier) {
318        useExponentialBackOff();
319        setBackOffMultiplier(multiplier);
320        return this;
321    }
322
323    /**
324     * Enables collision avoidance and sets the percentage used
325     */
326    public RedeliveryPolicy collisionAvoidancePercent(double collisionAvoidancePercent) {
327        useCollisionAvoidance();
328        setCollisionAvoidancePercent(collisionAvoidancePercent);
329        return this;
330    }
331
332    /**
333     * Sets the maximum redelivery delay if using exponential back off.
334     * Use -1 if you wish to have no maximum
335     */
336    public RedeliveryPolicy maximumRedeliveryDelay(long maximumRedeliveryDelay) {
337        setMaximumRedeliveryDelay(maximumRedeliveryDelay);
338        return this;
339    }
340
341    /**
342     * Sets the logging level to use for log messages when retries have been exhausted.
343     */
344    public RedeliveryPolicy retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
345        setRetriesExhaustedLogLevel(retriesExhaustedLogLevel);
346        return this;
347    }    
348
349    /**
350     * Sets the logging level to use for log messages when retries are attempted.
351     */    
352    public RedeliveryPolicy retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
353        setRetryAttemptedLogLevel(retryAttemptedLogLevel);
354        return this;
355    }
356
357    /**
358     * Sets the interval to log retry attempts
359     */
360    public RedeliveryPolicy retryAttemptedLogInterval(int logRetryAttemptedInterval) {
361        setRetryAttemptedLogInterval(logRetryAttemptedInterval);
362        return this;
363    }
364
365    /**
366     * Sets whether to log retry attempts
367     */
368    public RedeliveryPolicy logRetryAttempted(boolean logRetryAttempted) {
369        setLogRetryAttempted(logRetryAttempted);
370        return this;
371    }
372
373    /**
374     * Sets whether to log stacktrace for failed messages.
375     */
376    public RedeliveryPolicy logStackTrace(boolean logStackTrace) {
377        setLogStackTrace(logStackTrace);
378        return this;
379    }
380
381    /**
382     * Sets whether to log stacktrace for failed redelivery attempts
383     */
384    public RedeliveryPolicy logRetryStackTrace(boolean logRetryStackTrace) {
385        setLogRetryStackTrace(logRetryStackTrace);
386        return this;
387    }
388
389    /**
390     * Sets whether to log errors even if its handled
391     */
392    public RedeliveryPolicy logHandled(boolean logHandled) {
393        setLogHandled(logHandled);
394        return this;
395    }
396
397    /**
398     * Sets whether errors should be logged when a new exception occurred during handling a previous exception
399     */
400    public RedeliveryPolicy logNewException(boolean logNewException) {
401        setLogNewException(logNewException);
402        return this;
403    }
404
405    /**
406     * Sets whether to log exhausted errors
407     */
408    public RedeliveryPolicy logExhausted(boolean logExhausted) {
409        setLogExhausted(logExhausted);
410        return this;
411    }
412
413    /**
414     * Sets whether to log exhausted errors including message history
415     */
416    public RedeliveryPolicy logExhaustedMessageHistory(boolean logExhaustedMessageHistory) {
417        setLogExhaustedMessageHistory(logExhaustedMessageHistory);
418        return this;
419    }
420
421    /**
422     * Sets whether to log exhausted errors including message body (requires message history to be enabled)
423     */
424    public RedeliveryPolicy logExhaustedMessageBody(boolean logExhaustedMessageBody) {
425        setLogExhaustedMessageBody(logExhaustedMessageBody);
426        return this;
427    }
428
429    /**
430     * Sets the delay pattern with delay intervals.
431     */
432    public RedeliveryPolicy delayPattern(String delayPattern) {
433        setDelayPattern(delayPattern);
434        return this;
435    }
436
437    /**
438     * Disables redelivery by setting maximum redeliveries to 0.
439     */
440    public RedeliveryPolicy disableRedelivery() {
441        setMaximumRedeliveries(0);
442        return this;
443    }
444
445    /**
446     * Allow asynchronous delayed redelivery.
447     *
448     * @see #setAsyncDelayedRedelivery(boolean)
449     */
450    public RedeliveryPolicy asyncDelayedRedelivery() {
451        setAsyncDelayedRedelivery(true);
452        return this;
453    }
454
455    /**
456     * Controls whether to allow redelivery while stopping/shutting down a route that uses error handling.
457     *
458     * @param redeliverWhileStopping <tt>true</tt> to allow redelivery, <tt>false</tt> to reject redeliveries
459     */
460    public RedeliveryPolicy allowRedeliveryWhileStopping(boolean redeliverWhileStopping) {
461        setAllowRedeliveryWhileStopping(redeliverWhileStopping);
462        return this;
463    }
464    
465    /**
466     * Sets the reference of the instance of {@link org.apache.camel.spi.ExchangeFormatter} to generate the log message from exchange.
467     *
468     * @param exchangeFormatterRef name of the instance of {@link org.apache.camel.spi.ExchangeFormatter}
469     * @return the builder
470     */
471    public RedeliveryPolicy exchangeFormatterRef(String exchangeFormatterRef) {
472        setExchangeFormatterRef(exchangeFormatterRef);
473        return this;
474    }
475
476    // Properties
477    // -------------------------------------------------------------------------
478
479    /**
480     * @deprecated will be removed in the near future. Instead use {@link #getRedeliveryDelay()}
481     */
482    @Deprecated
483    public long getRedeliverDelay() {
484        return getRedeliveryDelay();
485    }
486
487    /**
488     * @deprecated will be removed in the near future. Instead use {@link #setRedeliveryDelay(long)}
489     */
490    @Deprecated
491    public void setRedeliverDelay(long redeliveryDelay) {
492        setRedeliveryDelay(redeliveryDelay);
493    }
494    
495    public long getRedeliveryDelay() {
496        return redeliveryDelay;
497    }
498
499    /**
500     * Sets the initial redelivery delay in milliseconds
501     */
502    public void setRedeliveryDelay(long redeliverDelay) {
503        this.redeliveryDelay = redeliverDelay;
504        // if max enabled then also set max to this value in case max was too low
505        if (maximumRedeliveryDelay > 0 && redeliverDelay > maximumRedeliveryDelay) {
506            this.maximumRedeliveryDelay = redeliverDelay;
507        }
508    }
509
510    public double getBackOffMultiplier() {
511        return backOffMultiplier;
512    }
513
514    /**
515     * Sets the multiplier used to increase the delay between redeliveries if
516     * {@link #setUseExponentialBackOff(boolean)} is enabled
517     */
518    public void setBackOffMultiplier(double backOffMultiplier) {
519        this.backOffMultiplier = backOffMultiplier;
520    }
521
522    public long getCollisionAvoidancePercent() {
523        return Math.round(collisionAvoidanceFactor * 100);
524    }
525
526    /**
527     * Sets the percentage used for collision avoidance if enabled via
528     * {@link #setUseCollisionAvoidance(boolean)}
529     */
530    public void setCollisionAvoidancePercent(double collisionAvoidancePercent) {
531        this.collisionAvoidanceFactor = collisionAvoidancePercent * 0.01d;
532    }
533
534    public double getCollisionAvoidanceFactor() {
535        return collisionAvoidanceFactor;
536    }
537
538    /**
539     * Sets the factor used for collision avoidance if enabled via
540     * {@link #setUseCollisionAvoidance(boolean)}
541     */
542    public void setCollisionAvoidanceFactor(double collisionAvoidanceFactor) {
543        this.collisionAvoidanceFactor = collisionAvoidanceFactor;
544    }
545
546    public int getMaximumRedeliveries() {
547        return maximumRedeliveries;
548    }
549
550    /**
551     * Sets the maximum number of times a message exchange will be redelivered.
552     * Setting a negative value will retry forever.
553     */
554    public void setMaximumRedeliveries(int maximumRedeliveries) {
555        this.maximumRedeliveries = maximumRedeliveries;
556    }
557
558    public long getMaximumRedeliveryDelay() {
559        return maximumRedeliveryDelay;
560    }
561
562    /**
563     * Sets the maximum redelivery delay.
564     * Use -1 if you wish to have no maximum
565     */
566    public void setMaximumRedeliveryDelay(long maximumRedeliveryDelay) {
567        this.maximumRedeliveryDelay = maximumRedeliveryDelay;
568    }
569
570    public boolean isUseCollisionAvoidance() {
571        return useCollisionAvoidance;
572    }
573
574    /**
575     * Enables/disables collision avoidance which adds some randomization to the
576     * backoff timings to reduce contention probability
577     */
578    public void setUseCollisionAvoidance(boolean useCollisionAvoidance) {
579        this.useCollisionAvoidance = useCollisionAvoidance;
580    }
581
582    public boolean isUseExponentialBackOff() {
583        return useExponentialBackOff;
584    }
585
586    /**
587     * Enables/disables exponential backoff using the
588     * {@link #getBackOffMultiplier()} to increase the time between retries
589     */
590    public void setUseExponentialBackOff(boolean useExponentialBackOff) {
591        this.useExponentialBackOff = useExponentialBackOff;
592    }
593
594    protected static synchronized Random getRandomNumberGenerator() {
595        if (randomNumberGenerator == null) {
596            randomNumberGenerator = new Random();
597        }
598        return randomNumberGenerator;
599    }
600
601    /**
602     * Sets the logging level to use for log messages when retries have been exhausted.
603     */    
604    public void setRetriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
605        this.retriesExhaustedLogLevel = retriesExhaustedLogLevel;        
606    }
607    
608    public LoggingLevel getRetriesExhaustedLogLevel() {
609        return retriesExhaustedLogLevel;
610    }
611
612    /**
613     * Sets the logging level to use for log messages when retries are attempted.
614     */    
615    public void setRetryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
616        this.retryAttemptedLogLevel = retryAttemptedLogLevel;
617    }
618
619    public LoggingLevel getRetryAttemptedLogLevel() {
620        return retryAttemptedLogLevel;
621    }
622
623    public int getRetryAttemptedLogInterval() {
624        return retryAttemptedLogInterval;
625    }
626
627    /**
628     * Sets the interval to log retry attempts
629     */
630    public void setRetryAttemptedLogInterval(int retryAttemptedLogInterval) {
631        this.retryAttemptedLogInterval = retryAttemptedLogInterval;
632    }
633
634    public String getDelayPattern() {
635        return delayPattern;
636    }
637
638    /**
639     * Sets an optional delay pattern to use instead of fixed delay.
640     */
641    public void setDelayPattern(String delayPattern) {
642        this.delayPattern = delayPattern;
643    }
644
645    public boolean isLogStackTrace() {
646        return logStackTrace;
647    }
648
649    /**
650     * Sets whether stack traces should be logged or not
651     */
652    public void setLogStackTrace(boolean logStackTrace) {
653        this.logStackTrace = logStackTrace;
654    }
655
656    public boolean isLogRetryStackTrace() {
657        return logRetryStackTrace;
658    }
659
660    /**
661     * Sets whether stack traces should be logged or not
662     */
663    public void setLogRetryStackTrace(boolean logRetryStackTrace) {
664        this.logRetryStackTrace = logRetryStackTrace;
665    }
666
667    public boolean isLogHandled() {
668        return logHandled;
669    }
670
671    /**
672     * Sets whether errors should be logged even if its handled
673     */
674    public void setLogHandled(boolean logHandled) {
675        this.logHandled = logHandled;
676    }
677
678    public boolean isLogNewException() {
679        return logNewException;
680    }
681
682    /**
683     * Sets whether errors should be logged when a new exception occurred during handling a previous exception
684     */
685    public void setLogNewException(boolean logNewException) {
686        this.logNewException = logNewException;
687    }
688
689    public boolean isLogContinued() {
690        return logContinued;
691    }
692
693    /**
694     * Sets whether errors should be logged even if its continued
695     */
696    public void setLogContinued(boolean logContinued) {
697        this.logContinued = logContinued;
698    }
699
700    public boolean isLogRetryAttempted() {
701        return logRetryAttempted;
702    }
703
704    /**
705     * Sets whether retry attempts should be logged or not
706     */
707    public void setLogRetryAttempted(boolean logRetryAttempted) {
708        this.logRetryAttempted = logRetryAttempted;
709    }
710
711    public boolean isLogExhausted() {
712        return logExhausted;
713    }
714
715    /**
716     * Sets whether exhausted exceptions should be logged or not
717     */
718    public void setLogExhausted(boolean logExhausted) {
719        this.logExhausted = logExhausted;
720    }
721
722    public boolean isLogExhaustedMessageHistory() {
723        // should default be enabled
724        return logExhaustedMessageHistory == null || logExhaustedMessageHistory;
725    }
726
727    /**
728     * Whether the option logExhaustedMessageHistory has been configured or not
729     *
730     * @return <tt>null</tt> if not configured, or the configured value as true or false
731     * @see #isLogExhaustedMessageHistory()
732     */
733    public Boolean getLogExhaustedMessageHistory() {
734        return logExhaustedMessageHistory;
735    }
736
737    /**
738     * Sets whether exhausted exceptions should be logged with message history included.
739     */
740    public void setLogExhaustedMessageHistory(boolean logExhaustedMessageHistory) {
741        this.logExhaustedMessageHistory = logExhaustedMessageHistory;
742    }
743
744    public boolean isLogExhaustedMessageBody() {
745        // should default be disabled
746        return logExhaustedMessageBody != null && logExhaustedMessageBody;
747    }
748
749    /**
750     * Whether the option logExhaustedMessageBody has been configured or not
751     *
752     * @return <tt>null</tt> if not configured, or the configured value as true or false
753     * @see #isLogExhaustedMessageBody()
754     */
755    public Boolean getLogExhaustedMessageBody() {
756        return logExhaustedMessageBody;
757    }
758
759    /**
760     * Sets whether exhausted message body/headers should be logged with message history included
761     * (requires logExhaustedMessageHistory to be enabled).
762     */
763    public void setLogExhaustedMessageBody(Boolean logExhaustedMessageBody) {
764        this.logExhaustedMessageBody = logExhaustedMessageBody;
765    }
766
767    public boolean isAsyncDelayedRedelivery() {
768        return asyncDelayedRedelivery;
769    }
770
771    /**
772     * Sets whether asynchronous delayed redelivery is allowed.
773     * <p/>
774     * This is disabled by default.
775     * <p/>
776     * When enabled it allows Camel to schedule a future task for delayed
777     * redelivery which prevents current thread from blocking while waiting.
778     * <p/>
779     * Exchange which is transacted will however always use synchronous delayed redelivery
780     * because the transaction must execute in the same thread context.
781     *
782     * @param asyncDelayedRedelivery whether asynchronous delayed redelivery is allowed
783     */
784    public void setAsyncDelayedRedelivery(boolean asyncDelayedRedelivery) {
785        this.asyncDelayedRedelivery = asyncDelayedRedelivery;
786    }
787
788    public boolean isAllowRedeliveryWhileStopping() {
789        return allowRedeliveryWhileStopping;
790    }
791
792    /**
793     * Controls whether to allow redelivery while stopping/shutting down a route that uses error handling.
794     *
795     * @param allowRedeliveryWhileStopping <tt>true</tt> to allow redelivery, <tt>false</tt> to reject redeliveries
796     */
797    public void setAllowRedeliveryWhileStopping(boolean allowRedeliveryWhileStopping) {
798        this.allowRedeliveryWhileStopping = allowRedeliveryWhileStopping;
799    }
800
801    public String getExchangeFormatterRef() {
802        return exchangeFormatterRef;
803    }
804
805    /**
806     * Sets the reference of the instance of {@link org.apache.camel.spi.ExchangeFormatter} to generate the log message from exchange.
807     */
808    public void setExchangeFormatterRef(String exchangeFormatterRef) {
809        this.exchangeFormatterRef = exchangeFormatterRef;
810    }
811
812}