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.Processor;
021    import org.apache.camel.model.LoggingLevel;
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://activemq.apache.org/camel/dead-letter-channel.html">Dead Letter
036     * Channel</a>
037     *
038     * @version $Revision: 69207 $
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 initialRedeliveryDelay(long initialRedeliveryDelay) {
088            getRedeliveryPolicy().initialRedeliveryDelay(initialRedeliveryDelay);
089            return this;
090        }
091    
092        public DeadLetterChannelBuilder maximumRedeliveries(int maximumRedeliveries) {
093            getRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
094            return this;
095        }
096    
097        public DeadLetterChannelBuilder maximumRedeliveryDelay(long maximumRedeliveryDelay) {
098            getRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
099            return this;
100        }
101    
102        public DeadLetterChannelBuilder useCollisionAvoidance() {
103            getRedeliveryPolicy().useCollisionAvoidance();
104            return this;
105        }
106    
107        public DeadLetterChannelBuilder useExponentialBackOff() {
108            getRedeliveryPolicy().useExponentialBackOff();
109            return this;
110        }
111    
112        public DeadLetterChannelBuilder retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
113            getRedeliveryPolicy().setRetriesExhaustedLogLevel(retriesExhaustedLogLevel);
114            return this;
115        }
116    
117        public DeadLetterChannelBuilder retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
118            getRedeliveryPolicy().setRetryAttemptedLogLevel(retryAttemptedLogLevel);
119            return this;
120        }
121    
122        /**
123         * Sets the logger used for caught exceptions
124         */
125        public DeadLetterChannelBuilder logger(Logger logger) {
126            setLogger(logger);
127            return this;
128        }
129    
130        /**
131         * Sets the logging level of exceptions caught
132         */
133        public DeadLetterChannelBuilder loggingLevel(LoggingLevel level) {
134            getLogger().setLevel(level);
135            return this;
136        }
137    
138        /**
139         * Sets the log used for caught exceptions
140         */
141        public DeadLetterChannelBuilder log(Log log) {
142            getLogger().setLog(log);
143            return this;
144        }
145    
146        /**
147         * Sets the log used for caught exceptions
148         */
149        public DeadLetterChannelBuilder log(String log) {
150            return log(LogFactory.getLog(log));
151        }
152    
153        /**
154         * Sets the log used for caught exceptions
155         */
156        public DeadLetterChannelBuilder log(Class log) {
157            return log(LogFactory.getLog(log));
158        }
159    
160        /**
161         * Sets the exception policy to use
162         */
163        public DeadLetterChannelBuilder exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
164            setExceptionPolicyStrategy(exceptionPolicyStrategy);
165            return this;
166        }
167    
168        /**
169         * Sets a processor that should be processed <b>before</b> a redelivey attempt.
170         * <p/>
171         * Can be used to change the {@link org.apache.camel.Exchange} <b>before</b> its being redelivered.
172         */
173        public DeadLetterChannelBuilder onRedelivery(Processor processor) {
174            setOnRedelivery(processor);
175            return this;
176        }
177    
178        // Properties
179        // -------------------------------------------------------------------------
180        public RedeliveryPolicy getRedeliveryPolicy() {
181            return redeliveryPolicy;
182        }
183    
184        /**
185         * Sets the redelivery policy
186         */
187        public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
188            this.redeliveryPolicy = redeliveryPolicy;
189        }
190    
191        public ProcessorFactory getDeadLetterFactory() {
192            if (deadLetterFactory == null) {
193                deadLetterFactory = new ProcessorFactory() {
194                    public Processor createProcessor() {
195                        return getDefaultDeadLetterEndpoint();
196                    }
197                };
198            }
199            return deadLetterFactory;
200        }
201    
202        /**
203         * Sets the default dead letter queue factory
204         */
205        public void setDeadLetterFactory(ProcessorFactory deadLetterFactory) {
206            this.deadLetterFactory = deadLetterFactory;
207        }
208    
209        public Processor getDefaultDeadLetterEndpoint() {
210            if (defaultDeadLetterEndpoint == null) {
211                defaultDeadLetterEndpoint = new RecipientList(getDefaultDeadLetterEndpointExpression());
212            }
213            return defaultDeadLetterEndpoint;
214        }
215    
216        /**
217         * Sets the default dead letter endpoint used
218         */
219        public void setDefaultDeadLetterEndpoint(Processor defaultDeadLetterEndpoint) {
220            this.defaultDeadLetterEndpoint = defaultDeadLetterEndpoint;
221        }
222    
223        public Expression getDefaultDeadLetterEndpointExpression() {
224            if (defaultDeadLetterEndpointExpression == null) {
225                defaultDeadLetterEndpointExpression = ExpressionBuilder
226                    .constantExpression(getDefaultDeadLetterEndpointUri());
227            }
228            return defaultDeadLetterEndpointExpression;
229        }
230    
231        /**
232         * Sets the expression used to decide the dead letter channel endpoint for
233         * an exchange if no factory is provided via
234         * {@link #setDeadLetterFactory(ProcessorFactory)}
235         */
236        public void setDefaultDeadLetterEndpointExpression(Expression defaultDeadLetterEndpointExpression) {
237            this.defaultDeadLetterEndpointExpression = defaultDeadLetterEndpointExpression;
238        }
239    
240        public String getDefaultDeadLetterEndpointUri() {
241            return defaultDeadLetterEndpointUri;
242        }
243    
244        /**
245         * Sets the default dead letter endpoint URI used if no factory is provided
246         * via {@link #setDeadLetterFactory(ProcessorFactory)} and no expression is
247         * provided via {@link #setDefaultDeadLetterEndpointExpression(Expression)}
248         *
249         * @param defaultDeadLetterEndpointUri the default URI if no deadletter
250         *                factory or expression is provided
251         */
252        public void setDefaultDeadLetterEndpointUri(String defaultDeadLetterEndpointUri) {
253            this.defaultDeadLetterEndpointUri = defaultDeadLetterEndpointUri;
254        }
255    
256        public Logger getLogger() {
257            return logger;
258        }
259    
260        public void setLogger(Logger logger) {
261            this.logger = logger;
262        }
263    
264        /**
265         * Sets the exception policy strategy to use for resolving the {@link org.apache.camel.model.ExceptionType}
266         * to use for a given thrown exception
267         */
268        public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
269            return exceptionPolicyStrategy;
270        }
271    
272        public void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
273            this.exceptionPolicyStrategy = exceptionPolicyStrategy;
274        }
275    
276        public Processor getOnRedelivery() {
277            return onRedelivery;
278        }
279    
280        public void setOnRedelivery(Processor onRedelivery) {
281            this.onRedelivery = onRedelivery;
282        }
283    
284        @Override
285        public String toString() {
286            return "DeadLetterChannelBuilder(" + (deadLetterFactory != null ? deadLetterFactory : defaultDeadLetterEndpoint) + ")";
287        }
288    }