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     */
017    package org.apache.camel.builder;
018    
019    import org.apache.camel.Endpoint;
020    import org.apache.camel.Expression;
021    import org.apache.camel.LoggingLevel;
022    import org.apache.camel.Predicate;
023    import org.apache.camel.Processor;
024    import org.apache.camel.processor.DefaultErrorHandler;
025    import org.apache.camel.processor.ErrorHandlerSupport;
026    import org.apache.camel.processor.Logger;
027    import org.apache.camel.processor.RedeliveryPolicy;
028    import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
029    import org.apache.camel.spi.RouteContext;
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import static org.apache.camel.builder.PredicateBuilder.toPredicate;
033    
034    /**
035     * The default error handler builder.
036     *
037     * @version $Revision: 792966 $
038     */
039    public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport {
040    
041        protected Logger logger;
042        protected ExceptionPolicyStrategy exceptionPolicyStrategy = ErrorHandlerSupport.createDefaultExceptionPolicyStrategy();
043        protected RedeliveryPolicy redeliveryPolicy;
044        protected Processor onRedelivery;
045        protected Predicate handledPolicy;
046        protected Processor failureProcessor;
047        protected Endpoint deadLetter;
048        protected String deadLetterUri;
049        protected boolean useOriginalMessage;
050    
051        public DefaultErrorHandlerBuilder() {
052        }
053    
054        public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
055            DefaultErrorHandler answer = new DefaultErrorHandler(processor, getLogger(), getOnRedelivery(), getRedeliveryPolicy(),
056                    getHandledPolicy(), getExceptionPolicyStrategy());
057            // configure error handler before we can use it
058            configure(answer);
059            return answer;
060        }
061    
062        public boolean supportTransacted() {
063            return false;
064        }
065    
066    
067        // Builder methods
068        // -------------------------------------------------------------------------
069        public DefaultErrorHandlerBuilder backOffMultiplier(double backOffMultiplier) {
070            getRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
071            return this;
072        }
073    
074        public DefaultErrorHandlerBuilder collisionAvoidancePercent(short collisionAvoidancePercent) {
075            getRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
076            return this;
077        }
078    
079        public DefaultErrorHandlerBuilder redeliverDelay(long delay) {
080            getRedeliveryPolicy().redeliverDelay(delay);
081            return this;
082        }
083    
084        public DefaultErrorHandlerBuilder delayPattern(String delayPattern) {
085            getRedeliveryPolicy().delayPattern(delayPattern);
086            return this;
087        }
088    
089        public DefaultErrorHandlerBuilder maximumRedeliveries(int maximumRedeliveries) {
090            getRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
091            return this;
092        }
093    
094        public DefaultErrorHandlerBuilder disableRedelivery() {
095            getRedeliveryPolicy().maximumRedeliveries(0);
096            return this;
097        }
098    
099        public DefaultErrorHandlerBuilder maximumRedeliveryDelay(long maximumRedeliveryDelay) {
100            getRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
101            return this;
102        }
103    
104        public DefaultErrorHandlerBuilder useCollisionAvoidance() {
105            getRedeliveryPolicy().useCollisionAvoidance();
106            return this;
107        }
108    
109        public DefaultErrorHandlerBuilder useExponentialBackOff() {
110            getRedeliveryPolicy().useExponentialBackOff();
111            return this;
112        }
113    
114        public DefaultErrorHandlerBuilder retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
115            getRedeliveryPolicy().setRetriesExhaustedLogLevel(retriesExhaustedLogLevel);
116            return this;
117        }
118    
119        public DefaultErrorHandlerBuilder retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
120            getRedeliveryPolicy().setRetryAttemptedLogLevel(retryAttemptedLogLevel);
121            return this;
122        }
123    
124        public DefaultErrorHandlerBuilder logStackTrace(boolean logStackTrace) {
125            getRedeliveryPolicy().setLogStackTrace(logStackTrace);
126            return this;
127        }
128    
129        /**
130         * Sets whether the exchange should be marked as handled or not.
131         *
132         * @param handled  handled or not
133         * @return the builder
134         */
135        public DefaultErrorHandlerBuilder handled(boolean handled) {
136            Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(handled));
137            return handled(expression);
138        }
139    
140        /**
141         * Sets whether the exchange should be marked as handled or not.
142         *
143         * @param handled  predicate that determines true or false
144         * @return the builder
145         */
146        public DefaultErrorHandlerBuilder handled(Predicate handled) {
147            this.setHandledPolicy(handled);
148            return this;
149        }
150    
151        /**
152         * Sets whether the exchange should be marked as handled or not.
153         *
154         * @param handled  expression that determines true or false
155         * @return the builder
156         */
157        public DefaultErrorHandlerBuilder handled(Expression handled) {
158            this.setHandledPolicy(toPredicate(handled));
159            return this;
160        }
161    
162        /**
163         * Sets the logger used for caught exceptions
164         *
165         * @param logger the logger
166         * @return the builder
167         */
168        public DefaultErrorHandlerBuilder logger(Logger logger) {
169            setLogger(logger);
170            return this;
171        }
172    
173        /**
174         * Sets the logging level of exceptions caught
175         *
176         * @param level the logging level
177         * @return the builder
178         */
179        public DefaultErrorHandlerBuilder loggingLevel(LoggingLevel level) {
180            getLogger().setLevel(level);
181            return this;
182        }
183    
184        /**
185         * Sets the log used for caught exceptions
186         *
187         * @param log the logger
188         * @return the builder
189         */
190        public DefaultErrorHandlerBuilder log(Log log) {
191            getLogger().setLog(log);
192            return this;
193        }
194    
195        /**
196         * Sets the log used for caught exceptions
197         *
198         * @param log the log name
199         * @return the builder
200         */
201        public DefaultErrorHandlerBuilder log(String log) {
202            return log(LogFactory.getLog(log));
203        }
204    
205        /**
206         * Sets the log used for caught exceptions
207         *
208         * @param log the log class
209         * @return the builder
210         */
211        public DefaultErrorHandlerBuilder log(Class log) {
212            return log(LogFactory.getLog(log));
213        }
214    
215        /**
216         * Sets the exception policy to use
217         *
218         * @return the builder
219         */
220        public DefaultErrorHandlerBuilder exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
221            setExceptionPolicyStrategy(exceptionPolicyStrategy);
222            return this;
223        }
224    
225        /**
226         * Sets a processor that should be processed <b>before</b> a redelivey attempt.
227         * <p/>
228         * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> its being redelivered.
229         *
230         * @return the builder
231         */
232        public DefaultErrorHandlerBuilder onRedelivery(Processor processor) {
233            setOnRedelivery(processor);
234            return this;
235        }
236    
237        /**
238         * Will use the original input {@link org.apache.camel.Message} when an {@link org.apache.camel.Exchange}
239         * is moved to the dead letter queue.
240         * <p/>
241         * <b>Notice:</b> this only applies when all redeliveries attempt have failed and the {@link org.apache.camel.Exchange}
242         * is doomed for failure.
243         * <br/>
244         * Instead of using the current inprogress {@link org.apache.camel.Exchange} IN message we use the original
245         * IN message instead. This allows you to store the original input in the dead letter queue instead of the inprogress
246         * snapshot of the IN message.
247         * For instance if you route transform the IN body during routing and then failed. With the original exchange
248         * store in the dead letter queue it might be easier to manually re submit the {@link org.apache.camel.Exchange}
249         * again as the IN message is the same as when Camel received it.
250         * So you should be able to send the {@link org.apache.camel.Exchange} to the same input.
251         * <p/>
252         * By default this feature is off.
253         *
254         * @return the builder
255         */
256        public DefaultErrorHandlerBuilder useOriginalMessage() {
257            setUseOriginalMessage(true);
258            return this;
259        }
260    
261        // Properties
262        // -------------------------------------------------------------------------
263    
264        public Processor getFailureProcessor() {
265            return failureProcessor;
266        }
267    
268        public void setFailureProcessor(Processor failureProcessor) {
269            this.failureProcessor = failureProcessor;
270        }
271    
272        public RedeliveryPolicy getRedeliveryPolicy() {
273            if (redeliveryPolicy == null) {
274                redeliveryPolicy = createRedeliveryPolicy();
275            }
276            return redeliveryPolicy;
277        }
278    
279        /**
280         * Sets the redelivery policy
281         */
282        public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
283            this.redeliveryPolicy = redeliveryPolicy;
284        }
285    
286        public Logger getLogger() {
287            if (logger == null) {
288                logger = createLogger();
289            }
290            return logger;
291        }
292    
293        public void setLogger(Logger logger) {
294            this.logger = logger;
295        }
296    
297        /**
298         * Sets the exception policy strategy to use for resolving the {@link org.apache.camel.model.OnExceptionDefinition}
299         * to use for a given thrown exception
300         */
301        public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
302            return exceptionPolicyStrategy;
303        }
304    
305        public void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
306            this.exceptionPolicyStrategy = exceptionPolicyStrategy;
307        }
308    
309        public Processor getOnRedelivery() {
310            return onRedelivery;
311        }
312    
313        public void setOnRedelivery(Processor onRedelivery) {
314            this.onRedelivery = onRedelivery;
315        }
316    
317        public Predicate getHandledPolicy() {
318            if (handledPolicy == null) {
319                handledPolicy = createHandledPolicy();
320            }
321            return handledPolicy;
322        }
323    
324        public void setHandledPolicy(Predicate handled) {
325            this.handledPolicy = handled;
326        }
327    
328        /**
329         * Sets the handled using a boolean and thus easier to use for Spring XML configuration as well
330         */
331        public void setHandled(boolean handled) {
332            handled(handled);
333        }
334    
335        public String getDeadLetterUri() {
336            return deadLetterUri;
337        }
338    
339        public void setDeadLetterUri(String deadLetterUri) {
340            this.deadLetter = null;
341            this.deadLetterUri = deadLetterUri;
342        }
343    
344        public Endpoint getDeadLetter() {
345            return deadLetter;
346        }
347    
348        public void setDeadLetter(Endpoint deadLetter) {
349            this.deadLetter = deadLetter;
350            this.deadLetterUri = deadLetter.getEndpointUri();
351        }
352    
353        public boolean isUseOriginalMessage() {
354            return useOriginalMessage;
355        }
356    
357        public void setUseOriginalMessage(boolean useOriginalMessage) {
358            this.useOriginalMessage = useOriginalMessage;
359        }
360    
361        protected Predicate createHandledPolicy() {
362            // should NOT be handled by default for default error handler
363            return PredicateBuilder.toPredicate(ExpressionBuilder.constantExpression(false));
364        }
365    
366        protected RedeliveryPolicy createRedeliveryPolicy() {
367            RedeliveryPolicy policy = new RedeliveryPolicy();
368            policy.disableRedelivery();
369            policy.setRedeliverDelay(0);
370            return policy;
371        }
372    
373        protected Logger createLogger() {
374            return new Logger(LogFactory.getLog(DefaultErrorHandler.class), LoggingLevel.ERROR);
375        }
376    
377        @Override
378        public String toString() {
379            return "DefaultErrorHandlerBuilder";
380        }
381    
382    }