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