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.Expression;
020    import org.apache.camel.LoggingLevel;
021    import org.apache.camel.Processor;
022    import org.apache.camel.processor.DeadLetterChannel;
023    import org.apache.camel.processor.ErrorHandlerSupport;
024    import org.apache.camel.processor.Logger;
025    import org.apache.camel.processor.RecipientList;
026    import org.apache.camel.processor.RedeliveryPolicy;
027    import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
028    import org.apache.camel.processor.interceptor.StreamCaching;
029    import org.apache.camel.spi.RouteContext;
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    
033    /**
034     * A builder of a <a
035     * href="http://camel.apache.org/dead-letter-channel.html">Dead Letter
036     * Channel</a>
037     *
038     * @version $Revision: 752532 $
039     */
040    public class DeadLetterChannelBuilder extends ErrorHandlerBuilderSupport {
041        private RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
042        private Processor onRedelivery;
043        private ExceptionPolicyStrategy exceptionPolicyStrategy = ErrorHandlerSupport.createDefaultExceptionPolicyStrategy();
044        private ProcessorFactory deadLetterFactory;
045        private Processor defaultDeadLetterEndpoint;
046        private Expression defaultDeadLetterEndpointExpression;
047        private String defaultDeadLetterEndpointUri = "log:org.apache.camel.DeadLetterChannel?level=error";
048        private Logger logger = DeadLetterChannel.createDefaultLogger();
049    
050        public DeadLetterChannelBuilder() {
051        }
052    
053        public DeadLetterChannelBuilder(Processor processor) {
054            this(new ConstantProcessorBuilder(processor));
055        }
056    
057        public DeadLetterChannelBuilder(ProcessorFactory deadLetterFactory) {
058            this.deadLetterFactory = deadLetterFactory;
059        }
060    
061        public ErrorHandlerBuilder copy() {
062            DeadLetterChannelBuilder answer = new DeadLetterChannelBuilder(deadLetterFactory);
063            answer.setRedeliveryPolicy(getRedeliveryPolicy().copy());
064            return answer;
065        }
066    
067        public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
068            Processor deadLetter = getDeadLetterFactory().createProcessor();
069            DeadLetterChannel answer = new DeadLetterChannel(processor, deadLetter, onRedelivery, getRedeliveryPolicy(), getLogger(), getExceptionPolicyStrategy());
070            StreamCaching.enable(routeContext);
071            configure(answer);
072            return answer;
073        }
074    
075        // Builder methods
076        // -------------------------------------------------------------------------
077        public DeadLetterChannelBuilder backOffMultiplier(double backOffMultiplier) {
078            getRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
079            return this;
080        }
081    
082        public DeadLetterChannelBuilder collisionAvoidancePercent(short collisionAvoidancePercent) {
083            getRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
084            return this;
085        }
086    
087        public DeadLetterChannelBuilder delay(long delay) {
088            getRedeliveryPolicy().delay(delay);
089            return this;
090        }
091    
092        public DeadLetterChannelBuilder delayPattern(String delayPattern) {
093            getRedeliveryPolicy().delayPattern(delayPattern);
094            return this;
095        }
096    
097        public DeadLetterChannelBuilder maximumRedeliveries(int maximumRedeliveries) {
098            getRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
099            return this;
100        }
101    
102        public DeadLetterChannelBuilder maximumRedeliveryDelay(long maximumRedeliveryDelay) {
103            getRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
104            return this;
105        }
106    
107        public DeadLetterChannelBuilder useCollisionAvoidance() {
108            getRedeliveryPolicy().useCollisionAvoidance();
109            return this;
110        }
111    
112        public DeadLetterChannelBuilder useExponentialBackOff() {
113            getRedeliveryPolicy().useExponentialBackOff();
114            return this;
115        }
116    
117        public DeadLetterChannelBuilder retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
118            getRedeliveryPolicy().setRetriesExhaustedLogLevel(retriesExhaustedLogLevel);
119            return this;
120        }
121    
122        public DeadLetterChannelBuilder retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
123            getRedeliveryPolicy().setRetryAttemptedLogLevel(retryAttemptedLogLevel);
124            return this;
125        }
126    
127        public DeadLetterChannelBuilder logStackTrace(boolean logStackTrace) {
128            getRedeliveryPolicy().setLogStackTrace(logStackTrace);
129            return this;
130        }
131    
132        /**
133         * Sets the logger used for caught exceptions
134         */
135        public DeadLetterChannelBuilder logger(Logger logger) {
136            setLogger(logger);
137            return this;
138        }
139    
140        /**
141         * Sets the logging level of exceptions caught
142         */
143        public DeadLetterChannelBuilder loggingLevel(LoggingLevel level) {
144            getLogger().setLevel(level);
145            return this;
146        }
147    
148        /**
149         * Sets the log used for caught exceptions
150         */
151        public DeadLetterChannelBuilder log(Log log) {
152            getLogger().setLog(log);
153            return this;
154        }
155    
156        /**
157         * Sets the log used for caught exceptions
158         */
159        public DeadLetterChannelBuilder log(String log) {
160            return log(LogFactory.getLog(log));
161        }
162    
163        /**
164         * Sets the log used for caught exceptions
165         */
166        public DeadLetterChannelBuilder log(Class log) {
167            return log(LogFactory.getLog(log));
168        }
169    
170        /**
171         * Sets the exception policy to use
172         */
173        public DeadLetterChannelBuilder exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
174            setExceptionPolicyStrategy(exceptionPolicyStrategy);
175            return this;
176        }
177    
178        /**
179         * Sets a processor that should be processed <b>before</b> a redelivey attempt.
180         * <p/>
181         * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> its being redelivered.
182         */
183        public DeadLetterChannelBuilder onRedelivery(Processor processor) {
184            setOnRedelivery(processor);
185            return this;
186        }
187    
188        // Properties
189        // -------------------------------------------------------------------------
190        public RedeliveryPolicy getRedeliveryPolicy() {
191            return redeliveryPolicy;
192        }
193    
194        /**
195         * Sets the redelivery policy
196         */
197        public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
198            this.redeliveryPolicy = redeliveryPolicy;
199        }
200    
201        public ProcessorFactory getDeadLetterFactory() {
202            if (deadLetterFactory == null) {
203                deadLetterFactory = new ProcessorFactory() {
204                    public Processor createProcessor() {
205                        return getDefaultDeadLetterEndpoint();
206                    }
207                };
208            }
209            return deadLetterFactory;
210        }
211    
212        /**
213         * Sets the default dead letter queue factory
214         */
215        public void setDeadLetterFactory(ProcessorFactory deadLetterFactory) {
216            this.deadLetterFactory = deadLetterFactory;
217        }
218    
219        public Processor getDefaultDeadLetterEndpoint() {
220            if (defaultDeadLetterEndpoint == null) {
221                defaultDeadLetterEndpoint = new RecipientList(getDefaultDeadLetterEndpointExpression());
222            }
223            return defaultDeadLetterEndpoint;
224        }
225    
226        /**
227         * Sets the default dead letter endpoint used
228         */
229        public void setDefaultDeadLetterEndpoint(Processor defaultDeadLetterEndpoint) {
230            this.defaultDeadLetterEndpoint = defaultDeadLetterEndpoint;
231        }
232    
233        public Expression getDefaultDeadLetterEndpointExpression() {
234            if (defaultDeadLetterEndpointExpression == null) {
235                defaultDeadLetterEndpointExpression = ExpressionBuilder
236                    .constantExpression(getDefaultDeadLetterEndpointUri());
237            }
238            return defaultDeadLetterEndpointExpression;
239        }
240    
241        /**
242         * Sets the expression used to decide the dead letter channel endpoint for
243         * an exchange if no factory is provided via
244         * {@link #setDeadLetterFactory(ProcessorFactory)}
245         */
246        public void setDefaultDeadLetterEndpointExpression(Expression defaultDeadLetterEndpointExpression) {
247            this.defaultDeadLetterEndpointExpression = defaultDeadLetterEndpointExpression;
248        }
249    
250        public String getDefaultDeadLetterEndpointUri() {
251            return defaultDeadLetterEndpointUri;
252        }
253    
254        /**
255         * Sets the default dead letter endpoint URI used if no factory is provided
256         * via {@link #setDeadLetterFactory(ProcessorFactory)} and no expression is
257         * provided via {@link #setDefaultDeadLetterEndpointExpression(Expression)}
258         *
259         * @param defaultDeadLetterEndpointUri the default URI if no deadletter
260         *                factory or expression is provided
261         */
262        public void setDefaultDeadLetterEndpointUri(String defaultDeadLetterEndpointUri) {
263            this.defaultDeadLetterEndpointUri = defaultDeadLetterEndpointUri;
264        }
265    
266        public Logger getLogger() {
267            return logger;
268        }
269    
270        public void setLogger(Logger logger) {
271            this.logger = logger;
272        }
273    
274        /**
275         * Sets the exception policy strategy to use for resolving the {@link org.apache.camel.model.OnExceptionDefinition}
276         * to use for a given thrown exception
277         */
278        public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
279            return exceptionPolicyStrategy;
280        }
281    
282        public void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
283            this.exceptionPolicyStrategy = exceptionPolicyStrategy;
284        }
285    
286        public Processor getOnRedelivery() {
287            return onRedelivery;
288        }
289    
290        public void setOnRedelivery(Processor onRedelivery) {
291            this.onRedelivery = onRedelivery;
292        }
293    
294        @Override
295        public String toString() {
296            return "DeadLetterChannelBuilder(" + (deadLetterFactory != null ? deadLetterFactory : defaultDeadLetterEndpoint) + ")";
297        }
298    }